在Go中,当程序启动时,包初始化过程遵循特定顺序:
1、当存在 import 包,会递归先初始化依赖包,依此再初始化第二个 import 包
Go
package main
import (
"fmt"
_ "inittest/dao" // 导入 dao 包, 会先初始化该包的内容,再执行主函数单元的 init()
)
// 主函数单元 init
func init() {
fmt.Println("主函数单元 init")
}
func main() {
fmt.Println("主函数单元执行 main 函数")
}
/* 执行结果:
dao 包下的 order 文件单元全局变量创建: OrderInfo
dao 包下的 order 文件单元 init
主函数单元 init
主函数单元执行 main 函数
*/
2、单个包内的初始化顺序为先初始化变量,再执行 init 函数。
Go
package main
import (
"fmt"
)
type Conf struct {
}
// 新建全局变量,会优先于 init() 函数初始化
var conf = NewConfig()
func NewConfig() *Conf {
fmt.Println("")
fmt.Println("主函数单元全局变量创建: conf")
return &Conf{}
}
// 主函数单元 init
func init() {
fmt.Println("主函数单元 init")
}
func main() {
fmt.Println("主函数单元执行 main 函数")
if conf == nil {
fmt.Println("配置项为空")
return
}
}
/* 执行结果:
主函数单元全局变量创建: conf
主函数单元 init
主函数单元执行 main 函数
*/
特别注意:
当一个包存在多个文件时,go 的初始化规则是:
①先处理所有文件的包级别变量(按文件中的出现顺序,但文件间的顺序不确定)
②再执行所有文件的 init 函数(按文件名字母顺序)

以下为完整示例,其中一个包中含有多个文件,项目结构如下:
inittest/
├── main.go # 项目入口文件
├── go.mod # Go 模块依赖配置
├── dao/ # 数据访问层 (Data Access Object)
│ └── order.go # 订单相关数据操作
└── root/ # 根包/初始化包
├── db.go # 数据库初始化配置
└── log.go # 日志初始化配置
执行结果:

包初始化顺序:

完整代码示例:
Go
// 文件位置 inittest\main.go
package main
import (
"fmt"
"inittest/dao" // 导入 dao 包
_ "inittest/root" // 导入 root 包, root 包下有多个文件单元, 会将所有文件单元的 import 包递归初始化,然后再将所有文件的变量初始化,最后将所有文件的 init 函数执行
)
type Conf struct {
}
// 新建全局变量
var conf = NewConfig()
func NewConfig() *Conf {
fmt.Println("")
fmt.Println("主函数单元全局变量创建: conf")
return &Conf{}
}
// 主函数单元 init
func init() {
fmt.Println("主函数单元 init")
}
func main() {
fmt.Println("主函数单元执行 main 函数")
if conf == nil {
fmt.Println("配置项为空")
return
}
if dao.OrderInfo != nil {
fmt.Println("主函数单元获取 dao 包下的全局变量 OrderInfo 成功")
return
}
}
Go
// 文件位置 inittest\root\log.go
package root
import "fmt"
type Logger struct {
}
// 新建全局变量
var Log = NewLogger()
func NewLogger() *Logger {
fmt.Println("root 包下的 log 文件单元全局变量创建: Log")
return &Logger{}
}
func init() {
fmt.Println("root 包下的 log 文件单元 init")
}
Go
// 文件位置 inittest\root\db.go
package root
import "fmt"
type DB struct {
}
// 新建全局变量
var Db = NewDB()
func NewDB() *DB {
fmt.Println("root 包下的 db 文件单元全局变量创建: db")
return &DB{}
}
func init() {
fmt.Println("root 包下的 db 文件单元 init")
}
Go
// 文件位置 inittest\dao\order.go
package dao
import "fmt"
type Order struct {
}
// 新建全局变量
var OrderInfo = NewOrder()
func NewOrder() *Order {
fmt.Println("dao 包下的 order 文件单元全局变量创建: OrderInfo")
return &Order{}
}
func init() {
fmt.Println("dao 包下的 order 文件单元 init")
fmt.Println("")
}