[译]Go的初始化及过程(Program initialization and execution)
原文链接
变量初始化
Go中变量通过以下几种方式分配空间:
- 通过定义(var)
- 通过new创建
- 通过赋值(:=)
- 通过字面合成(through a composite literal)
- 通过调用make
当没有明确的初始化时,会被赋予默认值。所有的变量初始化值为其类型所对应的零值,即
- boolean:false
- integer:0
- float:0.0
- string:””
- pointers/function/interface/slice/channel/map:nil
变量的初始化是递归地完成的,如对于一个数组,其默认值为各个元素的零值。
示例
以下定义效果相同:
var i int
var i int = 0
对象而言,以下3种方式定义亦等同
type T struct { i int; f float64; next *T }
//方式1
t := new(T)
//方式2
t.i == 0
t.f == 0.0
t.next == nil
//方式3
var t T
包的初始化
包级别的变量初始化顺序
- 按出现的顺序从前往后初始化
- 若某个变量需要依赖其它变量,则被依赖的变量先初始化
如
var (
a = c + b
b = f()
c = f()
d = 3
)
func f() int {
d++
return d
}
其初始化顺序为d,b,c,a
同时,变量也可以通过不带任何输入和输出参数的函数init来实现。init相关注意如下:
- 一个包可以出线多个init函数,一个源文件也可以包含多个init函数(Multiple such functions may be defined, even within a single source file. )。
- init函数在代码中不能被显示调用、不能被引用(赋值给函数变量),否则出现编译错误(The init identifier is not declared and thus init functions cannot be referred to from anywhere in a program.
)。 - 如果当前包包含多个依赖包(import),则先初始化依赖包(If a package has imports, the imported packages are initialized before initializing the package itself. )。
- 如果当前包有多个init函数,首先按照源文件名的字典序从前往后执行,若一个文件中出现多个init,则按照出现顺序从前往后执行(initialized by assigning initial values to all its package-level variables followed by calling all init functions in the order they appear in the source, possibly in multiple files, as presented to the compiler.)。
- 一个包被引用多次,如 A import B,C import B,A import C,B被引用多次,但B包只会初始化一次( If multiple packages import a package, the imported package will be initialized only once. )。
-
引入包,不可出现死循坏。即A import B,B import A,这种情况编译失败( The importing of packages, by construction, guarantees that there can be no cyclic initialization dependencies.
)。 - 包级别的变量初始化、init函数的执行,这两个操作会在goruntine 自己调用,且顺序调用,一次一个包(Package initialization—variable initialization and the invocation of init functions—happens in a single goroutine, sequentially, one package at a time.)。
- 一个init函数里可能会启动其它goroutine,即在初始化的同时启动新的goroutine。然而,初始化依旧是顺序的,即只有上一个init执行完毕,下一个才会开始( 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 invoke the next one until the previous one has returned.)。
程序执行(Program execution)
一个完整的Go程序会包含一个main包,main包中指定主函数main、及import需要的包。程序运行时,首先会执行主函数的初始化,然后运行main函数。
当main函数执行完毕时,程序退出,所有goroutine退出。即main函数结束后,不会等待所有的goroutines执行结束