
go 程序仅在显式导入(或间接依赖)某个包时才会执行其 init() 函数;若新包未被任何已启用代码引用,即使定义了 init() 也不会运行。
go 程序仅在显式导入(或间接依赖)某个包时才会执行其 init() 函数;若新包未被任何已启用代码引用,即使定义了 init() 也不会运行。
在 Go 中,init() 函数是包级初始化机制的核心:每个包可定义零个或多个 init() 函数,它们会在包被导入且所有依赖包初始化完成后、main() 执行前自动调用。但关键前提是——该包必须被实际导入并参与构建流程。
最常见的遗漏场景是:你创建了一个新包(例如 mypkg),并在其中定义了:
// mypkg/init.go
package mypkg
import "log"
func init() {
log.Println("mypkg initialized")
}
然而,若主程序(如 main.go)中未导入 mypkg,或仅以注释、未使用变量等方式“伪导入”,Go 编译器会将其视为未引用的死代码,直接从编译图中剔除——此时 init() 永远不会触发。
✅ 正确做法:确保包被显式导入。若仅需执行 init() 而不使用包内任何导出标识符(如函数、变量),应使用空白导入(blank import):
// main.go
package main
import (
_ "your-project/mypkg" // ← 使用下划线 "_" 表示仅触发初始化
)
func main() {
// mypkg.init() 已在此前自动执行
}
⚠️ 注意事项:
- 普通导入
import "your-project/mypkg"仅在代码中实际使用该包的导出项(如mypkg.DoSomething())时,才保证其init()被调用;若导入后未使用,部分 Go 版本(尤其启用-gcflags="-l"或模块精简模式时)可能优化掉该包。 - 空白导入
_ "path/to/pkg"是 Go 官方推荐的标准方式,明确传达“我需要此包的初始化副作用(如注册、全局配置、日志设置等)”。 - 避免依赖隐式导入:不要假设子包会被父包自动加载——Go 的导入是显式的、静态解析的,无自动递归加载机制。
- 可通过
go list -f '{{.Deps}}' .检查当前模块实际依赖的包列表,验证新包是否出现在其中。
总结:init() 不执行,本质是包未进入初始化链。请检查导入语句是否存在、是否生效,并优先采用空白导入确保初始化逻辑可靠触发。这是 Go 初始化模型的设计特性,而非 bug。










