go语言的初始化顺序,包,变量,init

htyu_0203_39 · · 11497 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

依次见例子代码:


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




有疑问加站长微信联系(非本文作者)

本文来自:CSDN博客

感谢作者:htyu_0203_39

查看原文:go语言的初始化顺序,包,变量,init

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:1006366459

11497 次点击  ∙  1 赞  
加入收藏 微博
被以下专栏收入,发现更多相似内容
2 回复  |  直到 2018-01-25 00:13:11
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传