单例模式通过包级变量和sync.Once确保全局唯一实例,适用于数据库连接等场景。使用sync.Once可保证并发安全的延迟初始化,而包初始化时直接创建实例则更简单且天然线程安全。推荐优先使用sync.Once方式,避免多协程下状态共享问题,同时注意测试时依赖注入的替代方案。

单例模式确保一个类只有一个实例,并提供一个全局访问点。在 Golang 中,由于没有类的概念,我们通过包级别的变量和函数来实现单例。关键在于控制实例的创建时机和并发安全。
使用 sync.Once 实现线程安全的单例
Go 标准库中的 sync.Once 能保证某个操作只执行一次,非常适合用于单例初始化,尤其是在多协程环境下。
package singleton
import (
立即学习“go语言免费学习笔记(深入)”;
"sync"
)
// 定义单例结构体
type Singleton struct {
Data string
}
var (
instance *Singleton
once sync.Once
)
// GetInstance 返回唯一的实例
func GetInstance() *Singleton {
once.Do(func() {
instance = &Singleton{
Data: "initialized",
}
})
return instance
}
直接初始化(包加载时创建)
如果不需要延迟初始化,可以在包加载时直接创建实例。这种方式更简单,且天然线程安全,因为 Go 的包初始化本身就是串行的。
package singleton
// 在包初始化时就创建实例
var instance = &Singleton{"initialized"}
type Singleton struct {
Data string
}
func GetInstance() *Singleton {
return instance
}
使用场景与注意事项
单例常用于数据库连接、配置管理、日志对象等只需要一个实例的地方。
- 需要延迟初始化且并发安全时,优先用 sync.Once
- 若实例创建开销小或必须提前初始化,可直接赋值
- 避免在单例中持有可变状态,防止多协程修改引发问题
- 测试时难以替换依赖,可考虑依赖注入替代单例
基本上就这些。sync.Once 是最推荐的方式,简洁又可靠。其他方法根据实际需求选择即可。不复杂但容易忽略并发问题,务必注意。









