在 Go 语言中,对于包级别的初始化来讲,首先会初始化包变量, 然后是 init() 函数(多个 init() 函数会按照文件名顺序逐个初始化)。
当包被引用的时候,执行顺序是从最深层包开始,依次往外进行初始化。
例如main.go函数导入了包A,包A又导入了包B。那么初始化的执行顺序为:包B -> 包A -> main.go。
下面是一个例子,mian.go导入了包A,包A又导入了包B。我们定义了一个GetA和GetB函数来实现包的导入关系:
package main
import (
"Study/study_init/A"
"fmt"
)
func init() {
fmt.Println("main函数中调用init函数")
}
func importA() {
A.GetA()
}
func main() {
}
----- A包 -----
package A
import (
"Study/study_init/B"
"fmt"
)
var _ = s()
func init() {
fmt.Println("在包A中初始化了 init 函数")
}
func GetA() {
}
func s() string {
fmt.Println("在包A中定义变量 s")
return "A"
}
func importB() {
B.GetB()
}
----- B包 -----
package B
import "fmt"
var _ = s()
func init() {
fmt.Println("在包B中初始化了 init 函数")
}
func s() string {
fmt.Println("在包B中定义变量 s")
return "B"
}
func GetB() {
}
结果为:
在包B中定义变量 s
在包B中初始化了 init 函数
在包A中定义变量 s
在包A中初始化了 init 函数
main函数中调用init函数
可以看见,当运行main.go的时候,先初始化了包B,然后是包A,最后是main.go。在每一个包中,是按照初始化变量->初始化init函数的顺序来初始化的。
总结:
- 如果存在包的引用,那么初始化执行顺序是从最深层包开始,依次往外进行初始化
- 包内变量先于 init() 函数初始化
- 一个包中可以有多个 init() 函数
- init() 函数只会被执行一次