网站开发需求文档prd模板,wordpress 图书主题,网站建设在哪能看,张家口网站seo前言
单例模式是常用的一种设计模式#xff0c;一般用于比如客户端、连接的创建等#xff0c;防止创建多个导致性能消耗。所以我认为单例模式的核心#xff0c;就是“防止重复”。本文将在Golang中进行单例模式的实现。
实现
版本1——检测-创建
最基础的版本#xff0…前言
单例模式是常用的一种设计模式一般用于比如客户端、连接的创建等防止创建多个导致性能消耗。所以我认为单例模式的核心就是“防止重复”。本文将在Golang中进行单例模式的实现。
实现
版本1——检测-创建
最基础的版本就是依照“防止重复”来实现。代码如下
package maintype Test1 struct {
}var t1 *Test1func main() {}func NewT1() *Test1 {if t1 nil {t1 Test1{}}return t1
}
可见只是在创建前进行了一个判定如果为空 再创建。不为空则直接返回。
但是这样版本存在有问题——即线程不安全。比如多个goroutine中同时运行其去创建那么就很容易导致创建重复。
对此解决方案也很简单——加锁即可。
版本2——加锁-检测-创建
很简单粗暴的加个锁——这样就能保证只有一个去进行检测、创建。规避了问题。
var mutex sync.Mutexfunc NewT1() *Test1 {mutex.Lock()defer mutex.Unlock()if t1 nil {t1 Test1{}}return t1
}
但是这样带来了新的问题频繁的加锁、删锁带来了巨大的性能损耗。诸如t1已经存在的情况本该直接返回即可但是却需要白白加锁一次。
版本3——检测-加锁-检测-创建
即所说的Check-Lock-Check模式。代码如下 func NewT1() *Test1 {if t1 nil {mutex.Lock()defer mutex.Unlock()if t1 nil {t1 Test1{}}}return t1
}
可以看到就是在最开始的lock之前进行一次检测。一个if判断的消耗还是很小的如果存在再进入加锁创建的流程。
在Golang中可以使用sync/atomic这个包原子化的加载一个标志来实现这套判断。 即
import sync
import sync/atomicvar initialized uint32
... // 此处省略func GetInstance() *singleton {if atomic.LoadUInt32(initialized) 1 { // 原子操作 return instance}mu.Lock()defer mu.Unlock()if initialized 0 {instance singleton{}atomic.StoreUint32(initialized, 1)}return instance
}
//此代码直接复制至原文——https://www.liwenzhou.com/posts/Go/singleton/版本4——Golang常用的方式
饿汉和懒汉式
饿汉
饿汉模式即像一个饿肚子人一样迫不及待的去享用美食。即 在程序加载的时候就创建并实例化因此也无需考虑并发等情况。
示例
package mainimport fmttype Singleton struct {// 在这里定义单例对象的属性
}var instance *Singleton createInstance()func createInstance() *Singleton {// 在这里创建并初始化单例对象return Singleton{// 初始化单例对象的属性}
}func GetInstance() *Singleton {return instance
}func main() {// 使用单例模式获取实例singletonInstance : GetInstance()// 使用单例实例fmt.Println(singletonInstance)
}
//此代码复制自原文——https://i6448038.github.io/2023/12/16/singleton/懒汉
顾名思义懒得管…等用到时候再创建。此时程序已经启动并正在运行此时创建实例可能会出现多线程的情况所以要考虑并发问题。
上述的实现代码便是懒汉模式。
参考资料 https://www.liwenzhou.com/posts/Go/singleton/ https://i6448038.github.io/2023/12/16/singleton/