土拔鼠的逆袭

go init()执行顺序

2021-02-04  本文已影响0人  我傻笑你跑掉

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

概述

init()一般用来做一些初始化工作, go允许定义多个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,目录结构如下

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.

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(),先定义的先执行.
上一篇 下一篇

猜你喜欢

热点阅读