在Go中,当程序启动时,包初始化过程遵循特定顺序:
1、当存在 import 包,会递归先初始化依赖包,依此再初始化第二个 import 包
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 函数。
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 # 日志初始化配置
执行结果:
包初始化顺序:
完整代码示例:
// 文件位置 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 } }// 文件位置 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") }// 文件位置 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") }// 文件位置 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("") }