去包初始化

Set*_*own 20 go

情况:

Go包A由3个.go文件组成,我在每个文件中使用来自另一个包B的函数.我必须在每个文件的开头导入包B.

题:

B实际上是初始化3次还是只有1次?

zzz*_*zzz 34

简答:初始化只会执行一次.

答案很长:引用相关规范部分 - 程序执行:

通过为其所有包级变量分配初始值,然后使用名称和签名调用任何包级函数来初始化没有导入的包.

func init()
Run Code Online (Sandbox Code Playgroud)

在其来源中定义.具有名称的包范围或文件范围标识符init只能声明为具有此签名的函数.即使在单个源文件中,也可以定义多个这样的函数; 它们以未指定的顺序执行.

在包中,初始化包级变量,并根据引用顺序确定常量值:如果A的初始化程序取决于B,则A将在B之后设置.依赖性分析不依赖于实际值.正在初始化的项目,仅限于它们在源中的外观.A取决于B,如果A的值包含B的提及,包含初始值提及B的值,或者提到递归提及B的函数.如果这种依赖性形成一个循环,那就是错误.如果两个项目不相互依赖,它们将按照它们在源中出现的顺序进行初始化,可能在多个文件中,如提供给编译器.由于每个包完成依赖性分析,如果A的初始化程序调用另一个引用B的包中定义的函数,它可以产生未指定的结果.

一个init函数不能在程序被称为从任何地方.特别是,init不能显式调用,也不能将指针init分配给函数变量.

如果包具有导入,则在初始化包本身之前初始化导入的包.如果多个包导入包P,则P将仅初始化一次.

通过构造导入包保证了初始化中不存在循环依赖性.

一个完整的程序是通过将一个名为main package的单个无转换与它所导入的所有一起链接来创建的.主包必须具有包名称main并声明一个main不带参数的函数并且不返回任何值.

func main() { … }
Run Code Online (Sandbox Code Playgroud)

程序执行从初始化主包然后调用该函数开始main.函数main返回时,程序退出.它不等待其他(非主要)goroutines完成.

包初始化 - 变量初始化和init函数调用- 在一个goroutine中顺序发生,一次发生一个包.一个init功能可能启动其他够程,可与初始化代码同时运行.但是,初始化总是对init函数进行排序:init在上一个函数返回之前,它不会启动.