golang实现设计模式之单例模式总结-代码、优缺点、适用场景

在日常业务开发中,适当应用设计模式,可以实现我们的业务需求,例如全局唯一配置,这里就需要用到单例模式。

什么情况下,我们可以使用单例模式呢?

这得考虑该模式的适用场景:

  • 用来控制类型实例的数量的,当需要确保一个类型只有一个实例

单例模式的适用场景:

  • 1.统计当前在线人数(网站计数器):用一个全局对象来记录。
  • 2.数据库连接池(控制资源):一般是采用单例模式,因为数据库连接是一种连接数据库资源,不易频繁创建和销毁,如缓存或者数据库等连接池对象。
  • 3.应用程序的日志(资源共享):一般日志内容是共享操作,需要在后面不断写入内容所以通常单例设计。
  • 4.应用配置:全局唯一实例。
  • 5.定义唯一属性:如特定的字符串。
  • 6.多线程的线程池设计。

单例模式优缺点

优点

  • 1.减少内存开销,尤其是频繁的创建和销毁实例。
  • 2.避免对资源对过多占用。

缺点

  • 1.没有抽象层,不能继承扩展很难。
  • 2.违背了“单一职责原则”,一个类只重视内部关系,而忽略外部关系。
  • 3.不适用于变化对象。
  • 4.滥用单例会出现一些负面问题:如连接池溢出,长时间不被使用,被GC。

单例模式的实现模式

在单例模式中,通常有懒汉模式和饿汉模式,区别在于是否程序启动时就创建实例。

饿汉模式

程序初始化时即创建,可能即使创建不一定使用,造成浪费,但可以及早暴露问题,定位问题。

该模式下的实现细节:

  • 1.单例类和构造方法不可导出,避免外部直接获取。
  • 2.全局变量中声明。
  • 3.初始化时,生成相关实例,并提供唯一外部接口获取实例。

代码实现:

package hungry
// 不可导出的变量、结构体、构造函数
type singletonHungry struct{}
var s *singletonHungry
func init() {
s = &singletonHungry{}
}
// 唯一外部接口
func GetInstance() *singletonHungry {
return s
}

懒汉模式

真正使用时再创建,需要注意并发安全问题,比如实例还未创建,有2个线程同时访问,这里就需要控制只会创建一个实例,通常来说可以通常加互斥锁实现,但也带来一定的性能问题,有时也需要通过 double check 解决。
该模式的实现细节:

  • 1.单例类和构造方法不可导出,避免外部直接获取。
  • 2.全局变量中声明。
  • 3.第一次创建时,通过GetInstance() xxx 创建实例。

比较优雅的 golang 实现中,我们可以通过 sync.Once 提供的接口实现,或者借助于 sync.Mutex + atomic.Load/atomic.Store 实现,二者实现是类似的,都能很好解决并发安全且只有一个实例的问题。

代码实现:

package lazy
import (
"sync"
"sync/atomic"
)
type singletonLazy struct{}
var s *singletonLazy
var once sync.Once
func GetInstance() *singletonLazy {
once.Do(func() {
s = &singletonLazy{}
})
return s
}
var done uint32
var mu sync.Mutex
func GetInstanceV2() *singletonLazy {
// 原子操作,减少锁开销,类似于sync.Once的处理流程
if atomic.LoadUint32(&done) == 1 {
return s
}
mu.Lock()
defer mu.Unlock()
if atomic.LoadUint32(&done) == 0 {
atomic.StoreUint32(&done, 1)
s = &singletonLazy{}
}
return s
}

参考文档:

posted on   进击的davis  阅读(466)  评论(0编辑  收藏  举报

相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南

导航

< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5
点击右上角即可分享
微信分享提示