情况:
一个 Go 包A由 3 组成.go
文件,并且我使用另一个包中的函数B在每个文件中。我必须导入包B在每个文件的开头。
问题:
是套餐B实际上初始化了3次还是只初始化了1次?
简短回答:初始化只会执行一次。
长答案:引用相关规范部分 -程序执行 http://golang.org/ref/spec#Program_execution:
没有导入的包的初始化方法是为其所有包级变量分配初始值,然后使用名称和签名调用任何包级函数
func init()
在其源代码中定义。带有名称的包范围或文件范围标识符init
只能声明为具有此签名的函数。即使在单个源文件中,也可以定义多个此类函数;它们以未指定的顺序执行。
在包内,根据引用顺序初始化包级变量并确定常量值:如果 A 的初始化器依赖于 B,则 A 将在 B 之后设置。依赖性分析不依赖于 A 的实际值。项目被初始化,仅在它们在源中出现时进行。如果 A 的值递归地包含对 B 的提及、包含其初始值设定项提及 B 的值或提及提及 B 的函数,则 A 依赖于 B。如果这种依赖关系形成一个循环,则是一个错误。如果两个项目不是相互依赖的,它们将按照它们在源代码中出现的顺序进行初始化,可能在多个文件中,如呈现给编译器的那样。由于依赖性分析是按包进行的,因此如果 A 的初始化程序调用在引用 B 的另一个包中定义的函数,则可能会产生未指定的结果。
An init
不能从程序中的任何地方引用函数。尤其,init
不能显式调用,也不能指向init
被分配给函数变量。
如果包具有导入,则导入的包会在初始化包本身之前初始化。如果多个包导入一个包P,P将只被初始化一次。
通过构造导入包可以保证初始化时不会出现循环依赖。
一个完整的程序是通过链接一个名为主包及其传递地导入的所有包。主包必须有包名main
并声明一个函数main
不带任何参数并且不返回任何值。
func main() { … }
程序执行首先初始化主包,然后调用函数main
。当函数main
返回,程序退出。它不会等待其他(非主)goroutine 完成。
包初始化——变量初始化和调用init
函数——发生在单个 goroutine 中,按顺序,一次一个包。一个init
函数可以启动其他 goroutine,它们可以与初始化代码同时运行。然而,初始化总是按顺序进行init
功能:不会启动下一个init
直到前一个返回。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)