Initialization
初始化参数
golang程序变量的初始化和变量的初始依赖相关- 初始化过程会存在多轮周期,每轮周期只初始化没有任何外部依赖的变量
- 初始化过程一直持续到全部变量完成初始化
- 如果依赖关系形成循环,编译器会直接报错(如
initialization cycle) - 包级别的初始化在
main函数执行之前、由主 goroutine 串行完成,因此初始化函数可以安全地使用 goroutine,但被启动的 goroutine 要等初始化全部结束后才会被调度
var (
a int = b + 1
b int = 1
)
func main() {
fmt.Println(a) // 2 第二轮初始化
fmt.Println(b) // 1 第一轮初始化
}
初始化顺序:第一轮先初始化没有依赖的 b = 1;第二轮再计算依赖 b 的 a = b + 1 = 2。声明顺序在前不代表初始化在前,依赖关系才是决定因素。
init
init()在包函数被执行前以及包内变量初始化后被调用变量初始化 -> init() -> main()- 每个包可以包含多个
init()函数,同一个文件也可以有多个,按声明顺序执行
init多用于初始化全局变量,先于main函数执行,并且不能被其他函数调用init函数没有传参和返回值,仅用来初始化当前包内的参数init的执行顺序和包的引入顺序相关:先初始化被导入的包,再执行当前包的init
import _ "net/http/pprof"表示仅导入包的init函数,不使用包内其他导出内容

完整执行顺序可总结为:
导入包的包级变量初始化 -> 导入包的 init() -> (递归向上) -> 当前包变量初始化 -> 当前包 init() -> main()
Example:
- 先执行全部变量的初始化
- 再执行
init函数 - 最后执行主函数
var T int64 = a()
func init() {
fmt.Println("init in main.go ")
}
func a() int64 {
fmt.Println("calling a()")
return 2
}
func main() {
fmt.Println("calling main")
}
/**calling a()
init in main.go
calling main**/
输出印证了顺序:a() 在变量初始化阶段最先被调用(即使它在 init 之后声明),然后是 init,最后才是 main。