Go语言之单例模式

Posted 陈谋人

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Go语言之单例模式相关的知识,希望对你有一定的参考价值。

前言

单例模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象 。在过去的很长时间里,很多开发人员都习惯使用php快速开发功能强大的系统,并且大多数情况下都不需要担心内部事务如何工作,也不需要担心线程安全性和并发性,单例模式在php中应用广泛,然而Go语言太容易实现并发了,以至于它在很多地方被不正确的使用了。

常见问题

/*** @program: Go** @description:单例模式并发不安全写法,多个协程操作容易都将创建该manager类型的实例并相互覆盖。无法保证它将在此处返回哪个实例。** @author: Mr.chen** @create: 2020-09-03 16:49**/package mainimport ( "fmt" )type manager struct{}var m *managerfunc Instance() *manager { if m == nil { m = new(manager) } return m}

单例模式并发不安全写法,多个协程操作容易都将创建该manager类型的实例并相互覆盖。无法保证它将在此处返回哪个实例,难调试以及没发现错误

实践与修改

改进1:利用互斥锁来初始化manager,通过加锁把对该函数的并发调用变成了串行。在manager已经初始化的情况下,我们只是返回缓存的manager实例。在高并发下,多个访问只能获取一个manager实例,在性能损耗多,串行时间慢,可能会存在一定的瓶颈。

/*** @program: Go** @description:利用互斥锁来实现go语言中的单例模式** @author: Mr.chen** @create: 2020-09-03 17:22**/package mainimport ( "fmt" "sync")var iMutex sync.Mutextype manager struct{}var m *managerfunc Instance() *manager { if m == nil { iMutex.Lock() defer iMutex.Unlock() m = new(manager) } return m}
改进2:Go语言惯用的单例模式,Go语言中标准库sync.Once,其中它有一个Do方法,该函数只是仅仅调用一次。所以可以不使用双重排它锁来保证线程的安全性。
/*** @program: Go** @description:利用sync.Once来实现go语言中的单例模式** @author: Mr.chen** @create: 2020-09-03 17:22**/package mainimport ( "fmt" "sync")var once sync.Oncetype manager struct{}var m *managerfunc Instance() *manager { once.Do(func() { m = &manager{} }) return m}
结论


程序员在写代码的时候必须养成多学多问多思考的习惯,写代码要养成严谨的习惯,特别是涉及到并发和并行代码时,我们更需要对代码进行审查。


以上是关于Go语言之单例模式的主要内容,如果未能解决你的问题,请参考以下文章

Go设计模式之单例模式

设计模式之单例模式

JAVA SCRIPT设计模式--创建型设计模式之单例模式

Python设计模式之单例模式

设计模式之单例模式

死磕GOF23之单例模式