Go 包A由 3 个.go文件组成,我在每个文件中使用另一个包B中的函数。我必须在每个文件的开头导入包B。
问题:
包B实际上初始化了 3 次还是只初始化了 1 次?
白猪掌柜的
浏览 207回答 1
1回答
开满天机
简短回答:初始化将只执行一次。长答案:引用相关规范部分 -程序执行:一个没有导入的包是通过为它的所有包级变量分配初始值然后调用任何包级函数来初始化的func init()在其来源中定义。具有名称的包范围或文件范围标识符init只能声明为具有此签名的函数。即使在单个源文件中,也可以定义多个这样的函数;它们以未指定的顺序执行。在一个包内,初始化包级变量,确定常量值,按照引用顺序:如果A的初始化器依赖于B,则A将设置在B之后。 依赖分析不依赖于实际值正在初始化的项目,仅在它们在源中出现时。如果 A 的值包含对 B 的提及、包含一个其初始值设定项提及 B 的值或递归提及提及 B 的函数,则 A 依赖于 B。如果这种依赖形成一个循环,则是错误的。如果两个项目不相互依赖,它们将按照它们在源代码中出现的顺序进行初始化,可能在多个文件中,如呈现给编译器一样。由于依赖项分析是针对每个包进行的,如果 A 的初始化程序调用另一个包中定义的引用 B 的函数,它会产生未指定的结果。一个init函数不能在程序中任何地方提到。特别是,init不能显式调用,也不能将指针init分配给函数变量。如果包有导入,则在初始化包本身之前初始化导入的包。如果多个包导入一个包 P,P 只会被初始化一次。包的导入,通过构造,保证初始化时不会有循环依赖。一个完整的程序是通过将一个称为主包的单个未导入包与其导入的所有包传递链接来创建的。主包必须具有包名main并声明一个main不带参数且不返回值的函数。func main() { … }程序执行首先初始化主包,然后调用函数main。当函数main返回时,程序退出。它不会等待其他(非主)goroutine 完成。包初始化——变量初始化和init函数调用——发生在一个 goroutine 中,一次一个包。一个init函数可能会启动其他 goroutine,这些 goroutine 可以与初始化代码同时运行。然而,初始化总是对init函数进行排序:init在前一个函数返回之前它不会启动下一个函数。