包初始化
init 函数的调用规则是什么?
init: 包初始化时自动调用一次;- 调用限制: 不能被代码显式调用;
- 使用位置: package 中可声明用于初始化的
init函数;
package config
var Loaded bool
func init() {
Loaded = true
}
- 声明限制: init 不接收参数、不返回值,同一个包甚至同一个文件可以声明多个 init;它们都由运行时初始化流程安排,而不是普通可调用函数值;
包初始化按什么依赖顺序执行?
- 多个 init: 按源码提交给编译器的文件顺序及文件内声明顺序执行;构建工具通常按文件名排序,不应把复杂业务依赖藏在文件名中;
- 包变量依赖: 变量初始化会先满足同包变量依赖,不能简单理解为只按书写顺序执行;
| 阶段 | 初始化对象 |
|---|---|
| 1 | 被导入 package |
| 2 | 当前 package 变量 |
| 3 | 当前 package 的 init |
package config
var Limit = base + 1 // 依赖 base,先初始化 base
var base = 2
func init() {
println(Limit) // 3:包变量已经初始化完成
}
- 生命周期: 包初始化在 main 之前完成;同一个被导入包只初始化一次,即使多个包都依赖它也不会重复执行 init;
- 并发边界: 包初始化流程顺序调用 init,但 init 自己启动的 goroutine 可以并发运行,不应假定它在 main 开始前必然完成;