Links

6.1 简介

我们知道 Go 语言运行时,首先会自动对所加载的包进行初始化,按照执行顺序,一个包的初始化任务可以分为如下三类:
  1. 1.
    依赖包的初始化逻辑 如果当前包依赖了其它的包,那么这些包的初始化逻辑需要首先完成,也可以看着是本包初始化任务的一部分
  2. 2.
    全局变量的赋值语句 全局变量、全局常量的赋值语句也是初始化逻辑的一部分,但常量的初始化工作在类型检查时已经完成,而变量的初始化则稍微复杂一些,例如如下代码:
    var nameAlias string = name + "!"
    var name string = func() string {
    return "Golang"
    }()
    const version = "1.2"
    var versionAlias string = version
    变量 nameAlias 依赖于 name ,因此其初始化顺序应该在 name 之后,而 name 的初始化需要执行一个函数,这需要在程序运行时才能完成;再看 versionAlias, 其初始化逻辑只是简单地拷贝常量 version 的值,而后者在编译时便可以确定,所以看起来 versionAlias 的初始化工作可以在编译时完成,以提升程序运行时的性能。
    由此可见,对于全局变量的赋值语句,编译器需要确定其初始化时间(编译时或运行时)、依赖关系以及初始化的顺序。
  3. 3.
    init 函数 由 init 函数定义包的初始化逻辑会在包加载时自动执行,并且一个包内可以申明任意多个 init 函数,其执行顺序与文件中的申明顺序一致
编译器会将以上三类初始化逻辑合并,并创建一个可执行的初始化任务,以便程序执行时调用。