依次见例子代码:
p1.go
package p1 import "fmt" //1.1 var x float32 = 1.2 //1.2 func init() { //1.3 fmt.Printf("p1 package, x:%f\n", x) //1.4 } func Donothing() { fmt.Println("do nothing.\n") }
a.go:
package main import "fmt" var WhatIsThe1 = AnswerToLife(2.1) //2.1 var WhatIsThe2 = AnswerToLife(2.2) //2.2 var WhatIsThe3 = AnswerToLife(2.3) //2.3 func init() { //3.1 fmt.Printf("init WhatIsThe in a.go `s init 3.1: %d\n", 2) } func init() { //3.2 fmt.Printf("init WhatIsThe in a.go`s init 3.2: %d\n", 3) }
testinit.go
package main import "p1" //1 import "fmt" var WhatIsThe4 = AnswerToLife(2.4) //2.4 var WhatIsThe5 = AnswerToLife(2.5) //2.5 var WhatIsThe6 = AnswerToLife(2.6) //2.6 func AnswerToLife(index float32) float32 { fmt.Printf("init package level variable, WhatIsThe: %f\n", index) return index } func init() { //3.3 fmt.Printf("init WhatIsThe in testinit.go`s init3.3: %d\n", 0) } func init() { //3.4 fmt.Printf("init WhatIsThe in testinit.go`s init3.4: %d\n", 1) } func main() { //4 p1.Donothing() //5 }
z.go
package main import "fmt" var WhatIsThe7 = AnswerToLife(2.7) //2.7 var WhatIsThe8 = AnswerToLife(2.8) //2.8 var WhatIsThe9 = AnswerToLife(2.9) //2.9 func init() { //3.5 fmt.Printf("init WhatIsThe in z.go`s init 3.5: %d\n", 4) } func init() { //3.6 fmt.Printf("init WhatIsThe in z.go`s init 3.6: %d\n", 5) }
代码文件贴出的顺序就是各大块之间的初始化顺序, 具体准确顺序请看,形如//1 , //2.1 这样的注释, 数值从小到大,小的先初始化,依次进行.
总结: 在一个go文件中, 初始化顺序规则: (1)引入的包 (2) 当前包中的变量常量 (3) 当前包的init (4)main函数
注意:
0. 当前go源文件中, 每一个被Import的包, 按其在源文件中出现顺序初始化。
1. 如果当前包有多个init在不同的源文件中, 则按源文件名以字典序从小到大排序,小的先被执行到, 同一包且同一源文件中的init,则按其出现在文件中的先后顺序依次初始化; 当前包的package level变量常量也遵循这个规则; 其实准确来说,应是按提交给编译器的源文件名顺序为准,只是在提交编译器之前, go命令行工具对源文件名按字典序排序了。
2. init只可以由go runtine自已调用, 我们在代码中不可以显示调用,也不可以被引用,如赋给a function variable。
3. 包A 引入包B , 包B又引入包C, 则包的初始化顺序为: C -> B -> A
4. 引入包,必须避免死循环,如 A 引 B , B引C, C引A.
5. 一个包被其它多个包引入,如A -> B ->C 和 H -> I -> C , C被其它包引了2次, 但是注意包C只被初始化一次。
6. 另一个大原则, 被依赖的总是先被初始化,当然呀。
7. main包总是被最后一个初始化,这很好理解,因为它总是依赖别的包。
代码在: https://github.com/yujinliang/test_init_sequence
reference:
http://stackoverflow.com/questions/17733220/go-package-initialization
https://golang.org/ref/spec#Program_initialization_and_execution
http://stackoverflow.com/questions/24790175/when-is-the-init-function-in-go-golang-run
此图引自:“Go语言程序设计”, Mark Summerfield著,人民邮电出版社
注意: 此文章只是我个人笔记, 如有错漏,请一定指正, 共同学习, 我的邮箱: htyu_0203_39@sina.com
有疑问加站长微信联系(非本文作者)