sync.Once是最安全的单例初始化方式天然解决并发首次调用竞态问题只执行一次闭包须作包级或结构体字段避免局部变量失效panic后会持续失败需自行兜底。Go 里 sync.Once 是最安全的单例初始化方式直接用 sync.Once 做初始化保护比手写锁或检查更可靠。它天然解决多协程并发首次调用时的竞态问题且只执行一次闭包不会重复初始化。常见错误是自己用 if instance nil sync.Mutex 判断但没加 double-check即锁内再判一次导致可能初始化多次或 panic。sync.Once 不关心你初始化的是什么类型只保证闭包只跑一次适合全局配置、DB 连接池、日志实例等不要把 sync.Once 放在函数局部变量里——它必须是包级或结构体字段否则每次调用都新建一个失去意义如果初始化函数可能 panicsync.Once 会记住这次失败后续调用仍会 panic需自行兜底比如用返回值重试逻辑用 init() 函数实现“编译期单例”要谨慎init() 确实只运行一次但它发生在包加载时无法按需延迟初始化也不支持传参或错误处理。一旦出错整个程序启动失败排查困难。典型误用场景在 init() 里连数据库、读配置文件、启动 HTTP server——这些操作都可能失败或耗时不该塞进 init()。立即学习“go语言免费学习笔记深入”init() 适合无副作用、确定成功的小型初始化比如注册 encoder、预设常量映射表若依赖外部资源如文件、网络务必改用 sync.Once 显式 GetXXX() 函数多个 init() 函数执行顺序由导入路径决定不可控别指望靠它做依赖排序带参数的单例不能靠全局变量硬编码需要传参比如 DB 地址、超时时间的单例不能直接定义全局变量然后在 init() 或包初始化时赋值。那样会导致参数固化、无法测试、难以复用。 WisPaper 复旦大学研发的AI学术搜索工具5分钟内筛选1000篇论文