去包初始化 [英] Go Package Initialization
问题描述
我必须在开始时导入包B的三个文件中的每一个,但是包B实际初始化了3次还是只有1次?
简短回答:只会执行一次初始化。
长答案:引用相关的规范部分 - 程序执行:
通过为所有包级变量分配初始值,然后调用任何名称和签名为
$ b的包级函数,初始化没有导入的包$ bfunc init()
资源。名称
init
的包范围或文件范围标识符只能被声明为具有此签名的函数。即使在单个源文件中也可以定义多个这样的函数;它们以未指定的顺序执行。
在包中,包级变量被初始化,常量值根据引用顺序被确定:如果A的初始化符取决于在B上,A将在B之后设置。依赖性分析不依赖于正在初始化的项目的实际值,仅在它们出现在源代码中。 A取决于B,如果A的值包含提及的B,包含一个初始值为B的值,或者递归地提到一个提到B的函数。如果这种依赖关系形成一个循环,这是一个错误。如果两个项目不相互依赖,它们将按照它们出现在源代码中的顺序进行初始化,可能以多个文件的形式呈现给编译器。由于依赖性分析是针对每个包完成的,因此如果A的初始化程序调用在引用B的另一个包中定义的函数,则它可能会产生未指定的结果。
init
函数不能从程序中的任何地方引用。特别是,不能显式调用init
,也不能将指向init
的指针赋给函数变量。 p>
如果包有导入,则在初始化包本身之前,将导入的包进行初始化。如果多个软件包导入一个软件包P,则P将只初始化一次。
通过构造导入软件包可确保在初始化过程中不存在循环依赖。 / p>
一个完整的程序是通过将一个名为主包的单个未导入包与其导入的所有包链接起来而创建的。主包必须有包名
main
,并声明一个不带参数且不返回任何值的函数main
p>
func main(){...}
通过初始化主包然后调用函数
main
来开始程序的执行。当函数main
返回时,程序退出。它不会等待其他(非主)goroutines完成。
包初始化变量初始化和调用
init
函数 - 在单个goroutine中按顺序发生,一次一个包。一个init
函数可以启动其他的goroutine,它可以与初始化代码同时运行。然而,初始化总是对init
函数进行排序:直到前一个返回,它才会启动下一个init
。 / p>
Go package A is composed of 3 .go files, and I use functions from another package B in each file.
I have to import package B at the beginning of each of the three files, but is package B actually initialized 3 times or only 1?
Short answer: Initialization will be performed only once.
Long answer: Quoting the relevant specification section - Program execution:
A package with no imports is initialized by assigning initial values to all its package-level variables and then calling any package-level function with the name and signature of
func init()
defined in its source. A package-scope or file-scope identifier with name
init
may only be declared to be a function with this signature. Multiple such functions may be defined, even within a single source file; they execute in unspecified order.Within a package, package-level variables are initialized, and constant values are determined, according to order of reference: if the initializer of A depends on B, A will be set after B. Dependency analysis does not depend on the actual values of the items being initialized, only on their appearance in the source. A depends on B if the value of A contains a mention of B, contains a value whose initializer mentions B, or mentions a function that mentions B, recursively. It is an error if such dependencies form a cycle. If two items are not interdependent, they will be initialized in the order they appear in the source, possibly in multiple files, as presented to the compiler. Since the dependency analysis is done per package, it can produce unspecified results if A's initializer calls a function defined in another package that refers to B.
An
init
function cannot be referred to from anywhere in a program. In particular,init
cannot be called explicitly, nor can a pointer toinit
be assigned to a function variable.If a package has imports, the imported packages are initialized before initializing the package itself. If multiple packages import a package P, P will be initialized only once.
The importing of packages, by construction, guarantees that there can be no cyclic dependencies in initialization.
A complete program is created by linking a single, unimported package called the main package with all the packages it imports, transitively. The main package must have package name
main
and declare a functionmain
that takes no arguments and returns no value.func main() { … }
Program execution begins by initializing the main package and then invoking the function
main
. When the functionmain
returns, the program exits. It does not wait for other (non-main) goroutines to complete.Package initialization—variable initialization and the invocation of
init
functions—happens in a single goroutine, sequentially, one package at a time. Aninit
function may launch other goroutines, which can run concurrently with the initialization code. However, initialization always sequences theinit
functions: it will not start the nextinit
until the previous one has returned.
这篇关于去包初始化的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!