去包初始化

时间:2013-07-18 20:25:28

标签: go

情况:

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

问题:

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

1 个答案:

答案 0 :(得分:33)

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

答案很长:引用相关的规范部分 - Program execution

  

通过为其所有包级变量分配初始值,然后使用名称和签名

调用任何包级函数来初始化没有导入的包。
func init()
     

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

     

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

     

无法从程序中的任何位置引用init函数。特别是,不能显式调用init,也不能将指向init的指针分配给函数变量。

     

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

     

通过构造导入包可以保证初始化中不存在循环依赖。

     

通过将名为主程序包的单个无导通程序包与其导入的所有程序包进行链接,可以创建一个完整的程序。主包必须具有包名main并声明一个不带参数且不返回任何值的函数main

func main() { … }
     

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

     

包初始化 - 变量初始化和init函数的调用 - 在单个goroutine中顺序发生,一次发生一个包。 init函数可以启动其他goroutine,它们可以与初始化代码同时运行。但是,初始化始终会对init函数进行排序:在上一个函数返回之前,它不会启动下一个init