
Go 中的 init() 是由编译器自动调用的特殊函数,不能手动调用;它会在包加载时自动执行,用于初始化包级变量和状态。
go 中的 `init()` 是由编译器自动调用的特殊函数,不能手动调用;它会在包加载时自动执行,用于初始化包级变量和状态。
在 Go 语言中,init() 函数具有严格的语义和调用时机约束:它不是普通函数,而是 Go 运行时机制的一部分。每个 Go 源文件可以定义一个或多个 init() 函数(无参数、无返回值),它们仅在包初始化阶段被自动执行一次,且执行顺序遵循明确规则:
- 所有包级变量初始化表达式先求值;
- 然后按源文件字典序(或依赖顺序)依次执行各 init() 函数;
- 最终才执行 main() 函数。
因此,以下写法是错误且非法的:
func main() {
init() // ❌ 编译报错:undefined: init
}
编译器会提示 undefined: init,因为 init 不是导出的标识符,也不属于用户可调用的函数符号——它是保留关键字级别的运行时钩子。
✅ 正确用法示例:
package main
import "flag"
var flagvar int
func init() {
flag.IntVar(&flagvar, "flagname", 1234, "help message for flagname")
}
func main() {
flag.Parse() // 必须显式调用,解析命令行参数
println("flagvar =", flagvar)
}
⚠️ 注意事项:
- init() 不能带参数、不能有返回值、不能被引用或赋值(如 var f = init 非法);
- 多个 init() 函数在同一文件中按出现顺序执行;跨文件则按包初始化依赖顺序执行;
- 若需复用初始化逻辑,应将其封装为普通函数(如 setupFlags()),再在 init() 或 main() 中调用;
- init() 中发生 panic 会导致整个程序启动失败,且堆栈信息可能难以定位,建议仅做轻量、确定性初始化。
总结:init() 是 Go 的“隐式启动钩子”,设计初衷是解耦初始化逻辑与业务入口,开发者应尊重其自动触发机制,避免试图手动调用——这既不符合语言规范,也无法通过编译。











