sync.once 是 go 中实现单例最推荐的方式,它通过 do 方法确保初始化函数仅执行一次。使用时定义一个 once 实例和单例变量,在 getinstance 函数中调用 once.do 来初始化对象,保证并发安全、代码简洁且性能良好。常见误区包括传参错误和复用 once 对象,此外还有全局变量、init 函数和加锁等其他单例实现方式,但均不如 sync.once 安全高效。

单例模式在Go语言中很常见,尤其是在需要确保某个对象只被初始化一次的场景下。实现方式有很多种,但最推荐、最安全的方式是使用标准库中的
sync.Once

sync.Once

type Once struct {
// contains filtered or unexported fields
}它只有一个方法
Do(f func())
f
立即学习“go语言免费学习笔记(深入)”;
这正好符合单例模式的需求:实例只创建一次,多次获取都是同一个对象。

实现起来非常简单,基本结构如下:
type Singleton struct{}
var instance *Singleton
var once sync.Once
func GetInstance() *Singleton {
once.Do(func() {
instance = &Singleton{}
})
return instance
}在这个例子中,无论多少个 goroutine 同时调用
GetInstance()
once.Do
instance
这种方式的优点很明显:
虽然
sync.Once
once.Do()
例如这样是可以的:
once.Do(func() {
instance = NewSingletonWithConfig(cfg)
})但不要试图把
Do
每个
sync.Once
Once
比如下面这种写法就有问题:
var once sync.Once
func InitA() { once.Do(doA) }
func InitB() { once.Do(doB) } // 错误!InitA执行后,once已经触发过了一旦其中一个初始化完成,另一个就永远不会再执行了。
除了
sync.Once
全局变量直接初始化
比如
var instance = &Singleton{}使用 init 函数初始化
利用包级
init()
加锁实现(比如 Mutex)
在并发访问时加锁判断是否已初始化
虽然可行,但每次都要加锁判断,性能不如
Once
相比之下,
sync.Once
once.Do()
基本上就这些。用
sync.Once
以上就是Golang如何实现单例模式 讲解sync.Once的线程安全用法的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号