go init()执行顺序

作者: 我傻笑你跑掉 | 来源:发表于2021-02-04 16:18 被阅读0次

    go允许定义多个init(),多个init()会涉及到执行先后的问题,本文将详细讲解这个问题.

    概述

    init()一般用来做一些初始化工作, go允许定义多个init(),根据init()重复场景不同,可以分为

    • 同文件 单文件中定义多个init()
    • 同模块 同模块下不同文件中定义了多个init()
    • 子模块 本模块和子模块都包含init()
    • 跨模块 多个被引用模块中均含init()

    要点秘诀:

    1. 涉及引用时,先加载的先执行
    2. 同一文件中,先定义的先执行

    同文件

    一个文件中出现多个init()时,执行顺序是从上往下按照定义顺序执行的,先定义的执行.

    package main
    
    import "fmt"
    
    func main(){
    
    }
    
    func init(){
        fmt.Println("first...")
    }
    
    func init(){
        fmt.Println("second...")
    }
    
    func init(){
        fmt.Println("third...")
    }
    

    执行结果

    first...
    second...
    third...
    

    调整一下定义顺序

    package main
    
    import "fmt"
    
    func main() {
    
    }
    
    func init() {
        fmt.Println("third...")
    }
    
    func init() {
        fmt.Println("second...")
    }
    func init() {
        fmt.Println("first...")
    }
    

    执行结果

    third...
    second...
    first...
    

    同模块

    同模块下定义多个init(),执行顺序是根据文件加载顺序来执行的,文件加载顺序就是文件名的字符串排序.

    代码测试一下,新建一个模块websit,目录结构如下

    • |---src
      • |---websit
        • |---acfun.go
        • |---bilibili.go
    • |---main.go

    main.go内容如下

    package main
    
    import (
        _ "website"
    )
    
    func main() {
    
    }
    
    

    acfun.go内容如下

    package website
    
    import "fmt"
    
    func init() {
        fmt.Println("AcFun弹幕视频网 - 认真你就输啦 (・ω・)ノ- ( ...")
    }
    

    bilibili.go内容如下
    ``go
    package website

    import "fmt"

    func init(){
    fmt.Println("哔哩哔哩 (゜-゜)つロ 干杯~-bilibili")
    }

    运行结果为
    ```text
    AcFun弹幕视频网 - 认真你就输啦 (・ω・)ノ- ( ...
    哔哩哔哩 (゜-゜)つロ 干杯~-bilibili
    

    文件名排序,acfun.gobilibili.go之前,所以acfun.go会先被加载,文件中的init()会先被执行.

    如果acfun.go中定义了多个init(),执行顺序和同文件一样.

    子模块

    与同模块一样,先被加载的先执行.

    修改上述demo文件路径,增加个子模块login.

    • |---src
      • |---websit
        • |---login
          • |----login.go
        • |---acfun.go
        • |---bilibili.go
    • |---main.go

    login.go内容如下

    package login
    
    import "fmt"
    
    func init(){
        fmt.Println("login...")
    }
    

    修改acfun.go

    package website
    
    import (
        "fmt"
        _ "website/login"
    )
    
    func init() {
        fmt.Println("AcFun弹幕视频网 - 认真你就输啦 (・ω・)ノ- ( ...")
    }
    

    执行结果:

    login...
    AcFun弹幕视频网 - 认真你就输啦 (・ω・)ノ- ( ...
    哔哩哔哩 (゜-゜)つロ 干杯~-bilibili
    

    ps:go模块加载详解请查阅另外一篇文章.

    多模块

    1. 同子模块一样,哪个模块先被import就先被加载.
    2. 这个模块如果有子模块,会先加载子模块
    3. 如果子模块中有多个文件,根据文件名排序决定文件加载顺序
    4. 一个文件被加载时,如果定义多个init(),先定义的先执行.

    相关文章

      网友评论

        本文标题:go init()执行顺序

        本文链接:https://www.haomeiwen.com/subject/nubbtltx.html