Go中的单例模式:饿汉、懒惰还是双重检查?
联系作者@:微信公众号,Medium,LinkedIn,Twitter
单例模式(Singleton Pattern)恐怕是最为人熟知的一种设计模式了。它同样也是创建型模式的一种。当某个struct只允许有一个实例的时候,我们会用到这种设计模式。这个struct的唯一的实例被称为单例对象。它确保一个类只有一个实例,并提供一个全局访问点。在Go语言中,单例模式的实现相对简单,主要通过使用sync.Once
和全局变量来保证线程安全。
什么是单例模式
单例模式的核心思想是:
- 唯一性:在整个应用程序中只存在一个实例。
- 全局访问:提供一个全局的访问点来获取该实例。
适用场景
- 需要控制资源的访问,例如数据库连接、线程池等。
- 应用程序的配置管理。
- 日志管理器,确保日志写入的统一性。
Go语言中的实现方法
1. 基于init()函数的饿汉式(Eager Initialization)
在init()
函数中创建单例。因为一个包中每个文件的init()
函数都只会调用一次,这样就可以保证只有一个实例会被创建。但是在程序启动时就创建单例实例,这种方式简单但可能造成资源浪费。
2. 懒汉式(Lazy Initialization)
懒汉式在首次使用时创建实例,使用sync.Once
确保线程安全。
sync.Once
可以通过这篇文章了解:SyncOnce You Should Know in Golang - Tfrain - Tfrain’s Bilingual Blog
3. 双重检查锁(Double-Checked Locking)
双重检查锁是一种优化的懒汉式实现,减少了加锁的开销。
如果你读了 SyncOnce You Should Know in Golang - Tfrain - Tfrain’s Bilingual Blog,会发现其实双重检查锁和使用 sync.Once
没有什么区别。因为他们用了类似的结构和思路,比如都用到了原子变量和锁:
1 | done atomic.Uint32 |
sync.Once
大概率会比你自己实现的双重检查锁性能更好,而且开箱即用。
总结
优点:
- 控制了对象的创建,避免了资源浪费。
- 提供了全局访问点,便于管理共享资源。
缺点:
- 难以进行单元测试,因为依赖于全局状态。
- 滥用单例可能导致代码难以维护和扩展。
单例模式在Go语言中的实现主要依赖于全局变量和sync.Once
,以确保线程安全和唯一性。选择合适的实现方式可以根据具体需求来决定:
- 饿汉式适合于启动时就需要创建实例的情况。
- 懒汉式和双重检查锁更适合于需要延迟初始化且要考虑并发安全的场景。
更多内容
最近文章:
随机文章:
更多该系列文章,参考medium链接:
https://wesley-wei.medium.com/list/you-should-know-in-golang-e9491363cd9a
English post: https://programmerscareer.com/golang-singleton-pattern/
作者:微信公众号,Medium,LinkedIn,Twitter
发表日期:原文在 2024-11-23 22:22 时创作于 https://programmerscareer.com/zh-cn/golang-singleton-pattern/
版权声明:自由转载-非商用-非衍生-保持署名(创意共享3.0许可证)
评论