去包初始化 [英] Go Package Initialization

查看:202
本文介绍了去包初始化的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

Go包A由3个.go文件组成,我在每个文件中使用另一个包B中的函数。



我必须在开始时导入包B的三个文件中的每一个,但是包B实际初始化了3次还是只有1次?

解决方案

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



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


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


$ b的包级函数,初始化没有导入的包$ b

  func 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 to init 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 function main 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 function main 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. An init function may launch other goroutines, which can run concurrently with the initialization code. However, initialization always sequences the init functions: it will not start the next init until the previous one has returned.

这篇关于去包初始化的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆