在GO程序中,初始化的几个结构通常为:包(package),常量(const),变量(var),init()和main()。
接下来我说一下这几个结构的执行顺序:
当 A 没有引入其他包的情况下执行顺序是:package > const > var > init() > main()
当 A 里引入了包 B 的时候会有一些变化,程序会先执行包 B 里面的import,const,var,init()函数,执行完毕之后跳回 A ,继续按照顺序执行。
如果包B里面引入了C包,如上规则执行
--------------------- ---------------------------------------------------------------------------------------------------------------------------------------------------------
Go 语言在声明变量时,自动对变量对应的内存区域进行初始化操作。每个变量会初始化其类型的默认值,例如:
- 整型和浮点型变量的默认值为 0。
- 字符串变量的默认值为空字符串。
- 布尔型变量默认为 bool。
- 切片、函数、指针变量的默认为 nil。
- ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
.import机制
● main -> import pkg1 -> const -> var ... -> init() -> main()
● pkg1 -> import pkg2 -> const -> ...
● pkg2 -> ...
import(
"time" //普通写法
. "fmt" //使用此包内的成员时不带fmt前缀
j "encoding/json" //json包重命名
扫描二维码关注公众号,回复: 6393936 查看本文章// 引入包顺序遵循 标准库,项目包,第三方包
)
不要使用相对路径引入包(以GOPATH/src作为根目录)
import 后面跟着包路径。go语言的惯例只是一个特例,即恰好目录名与包名一致。import中的foo只是一个文件系统的路径。而下面foo.Foo()中的foo则是包名。而这个包是在src/foo目录下的源码中找到的。
2. init函数
init函数可以在任何包中有0个或1个或多个; init函数和main函数都不能被显示调用;
但这无论是对于可读性还是以后的可维护性来说,强烈建议用户在一个package中每个文件只写一个init函数。
3. 变量初始化顺序
全局变量初始化若有需要依赖其它变量,则被依赖的变量先初始化。但局部变量这样的话就会报错
var a int = b + 1
var b int = 1
下面例子会报 "initialization loop" 错误
var a = b
var b = c
var c = a
没有依赖关系的初始化的顺序不一定。
当程序里面只有一个goroutine时候,虽然编译器和CPU由于开启了优化功能可能调整读写操作的顺序,但是这个调整是不会影响程序的执行正确性:
a := 1//1
b := 2//2
c := a + b //3
...
如上代码由于编译器和cpu的优化,实际运行时候可能代码(2)先运行,然后代码(1)后执行,但是由于代码(3)依赖代码(1)和代码(2)创建的变量,所以代码(1)和(2)不会被放到代码(3)后运行,也就是说编译器和CPU在不改变程序正确性的前提下才会对指令进行重排序,所以上面代码在单一goroutine时候并不会存在问题,也就是在单一goroutine 中Happens Before所要表达的顺序就是程序执行的顺序。
4. 类型检查
Go编译器可以从初始化表达式的右值推导出该变量应该声明为哪种类型,这让Go语言看起来有点像动态类型语言,但是Go语言实际上是强类型语言(静态类型语言