Go中实现线程安全单例最推荐用sync.Once,它保证初始化逻辑仅执行一次且并发安全;其次可选init()饿汉式(启动即创建)或sync.Mutex(不推荐,易出错)。
在 Go 语言中,实现线程安全的单例模式最推荐的方式是使用 sy —— 它天然保证初始化逻辑只执行一次,且并发安全,无需手动加锁或判断。
nc.Once
这是最常用、最简洁、最安全的做法。单例实例在第一次调用时创建,后续直接返回已创建的实例。
instance *Singleton)和一个 sync.Once 实例once.Do() 包裹初始化逻辑示例:
func GetInstance() *Singleton {虽然可行,但容易出错:比如忘记加锁、重复加锁、或在 return 前未解锁。性能也略低于 sync.Once(每次调用都要加锁)。
mu sync.Mutex 和私有实例变量mu.Lock(),检查是否已初始化;若否,则初始化并解锁;若是,解锁后直接返回利用包初始化阶段(init() 函数)完成实例创建,天然线程安全,且无运行时开销。
sync.Once 方式示例:
var instance = &Singleton{}不要用双重检查锁定(Double-Check Locking)模仿 Java 写法 —— Go 的内存模型和编译器优化会让这类写法难以保证正确性,且没必要。
sync.Once 放在结构体里(它不是可复制类型),应作为包级变量基本上就这些。用 sync.Once 是 Go 社区共识,简洁、安全、高效,无需过度设计。