包的初始化
保级变量会按声明的顺序进行初始化,如果依赖其他变量,则会在其他变量之后进行初始化。
更确切的说,如果包级变量还没初始化并且没有初始化表达式或者表达式中不包含对其他未初始化变量的依赖,那么会认为它正在等待初始化。初始化过程会从最早声明的变量开始向下一个包级变量重复,直到没有需要初始化的变量。
如果在初始化过程完成后还有未初始化的变量,那么这些变量可能是循环初始化了,这事程序不是合法的。
在多个文件中变量的声明顺序会依据编译时文件出现的顺序:声明在第一个文件中的变量优先于第二个文件中声明的变量,依此类推。
对依赖关系的分析不会根据变量的具体值,它只分析在源码中是否引用了其他变量。例如,如果变量 x 的初始化表达式引用了变量 y 那么 x 就依赖于 y:
引用一个变量或者函数中用到了一个变量
引用了一个方法值
m
或者方法表达式t.m
(这里的静态类型t
不是借口类型,并且方法m
是t
方法集中的方法)。t.m
的返回值不会在此时影响。变量,函数,或者方法 x 依赖变量 y
依赖分析会在每个包中执行;他只考虑当前包中的析变量,函数,和方法。
例如,给定声明:
var (
a = c + b
b = f()
c = f()
d = 3
)
func f() int {
d++
return d
}
初始化顺序为 d,b,c,a。
变量可以在包中声明的初始化函数 init
中进行初始化,它没有参数和返回值。
func init() {}
可以为每个包定义多个该函数,甚至在一个文件中也可以。并且不会声明该该标识符。因此 init 函数不能在程序中调用。
还未导入的包会先初始化包级的变量然后按照 init
函数在源码中的顺序调用,它可能在包的多个文件中。如果需要导入一个包,它会在初始化自己之前先初始化这个需要导入的包。如果导入一个包多次,那这个包只会初始化一次。导入的包不能存在循环引用。
包的初始化——变量初始化和对 init 函数的调用会按顺序发生在同一个 goroutine 中。 init
函数可能会启动其他 goroutine。不过一般 init
函数都是按序进行初始化的:它只在上一步已经执行完成时才会调用下一个步骤。
确保初始化行为是可以复现的,构建系统鼓励在同一个包中包含多个文件这些文件在编译器中会以字母排序。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论