[go] 单例模式

单例模式

确保类只有一个实例,并提供一个全局的访问点。

  • 单例(Singleton)类声明了一个名为getInstance的方法来返回其所属类的一个相同实例。

  • 单例的构造函数必须对客户端的代码隐藏。调用getInstance方法必须是获取单例对象的唯一方式。

优缺点

1.优点

你可以肯定,一个类只有一个实例。

有助于获得该实例的全局访问点。

仅在首次请求单例对象时对其进行初始化。

2.缺点

  • 它违反了单一责任原则。该模式同时解决了两个问题。
  1. 保证一个类只有一个实例
  2. 为该实例提供一个全局访问节点
  • 单例模式可以掩盖糟糕的设计。例如,当程序组件对彼此了解太多。

  • 不是线程安全的,你写的代码要确保为所有线程只创建一个实例。

  • 单例的客户端代码单元测试可能会比较困难, 因为许多测试框架以基于继承的方式创建模拟对象。 由于单例类的构造函数是私有的, 而且绝大部分语言无法重写静态方法, 所以你需要想出仔细考虑模拟单例的方法。 要么干脆不编写测试代码, 或者不使用单例模式。

使用场景

  • 如果程序中的某个类对于所有客户端只有一个可用的实例, 可以使用单例模式。
  • 如果你需要更加严格地控制全局变量, 可以使用单例模式。

参考代码

这里我们分两个例子吧,一个是简单的单例实现,另外一个是解决异步情况可能会出现的问题
sample

go 复制代码
type single struct{}

var normalSingleInstance *single

func getNormalSingle() *single {
	if normalSingleInstance == nil {
		fmt.Println("creating single instance")
		normalSingleInstance = new(single)
	} else {
		fmt.Println("single instance already created")
	}
	return normalSingleInstance
}

func main() {
	for i := 0; i < 10; i++ {
		getNormalSingle()
	}
}

输出:

go 复制代码
creating single instance
single instance already created
single instance already created
single instance already created
single instance already created
single instance already created
single instance already created
single instance already created
single instance already created
single instance already created

multithread

go 复制代码
type single struct{}

var lock = &sync.Mutex{}

var multiThreadSafeInstance *single

func getMultiThreadSafeInstance() *single {
	if multiThreadSafeInstance == nil {
		lock.Lock()
		defer lock.Unlock()
		if multiThreadSafeInstance == nil {
			fmt.Println("creating multi-thread safe instance now.")
			multiThreadSafeInstance = new(single)
		} else {
			fmt.Println("multi-thread safe instance already created.")
		}
	} else {
		fmt.Println("multi-thread safe instance already created.")
	}

	return multiThreadSafeInstance
}

func main() {
	for i := 0; i < 2; i++ {
		go func() {
			for j := 0; j < 5; j++ {
				getMultiThreadSafeInstance()
			}
		}()
	}
	select {}
}

输出:

go 复制代码
creating multi-thread safe instance now. 
multi-thread safe instance already created. 
multi-thread safe instance already created. 
multi-thread safe instance already created. 
multi-thread safe instance already created. 
multi-thread safe instance already created. 
multi-thread safe instance already created. 
multi-thread safe instance already created. 
multi-thread safe instance already created. 
multi-thread safe instance already created.
相关推荐
利威尔xu8 小时前
Go IM 源码实战(14):本地缓存快 3000 倍,失效却难 10 倍
后端·缓存·微服务·面试·golang
幸运小猿8 小时前
模拟慢上传-处理超时重试image 丢失线上问题
前端·javascript·html
利威尔xu9 小时前
Go IM 源码实战(13):30 个会话只有 2 个红点,未读数错在三条路径
redis·后端·微服务·面试·golang
FungLeo10 小时前
成为全栈·Go 后端篇·从 Node SQLite 到 PostgreSQL:把迁移做成独立交付物
postgresql·golang·sqlite·go·数据库迁移·成为全栈
速易达网络11 小时前
ECharts 图表制作完全指南:从零到可视化实战
前端·javascript·echarts
paopaokaka_luck12 小时前
灾害应急物资管理系统(AI应急助手、Echarts可视化数据看板、捐赠入库联动、 物资全流程管理、库存变动追溯、灾情资讯与互动反馈、物资发放公示)
java·前端·javascript·spring boot·mysql·tomcat·echarts
kyriewen12 小时前
我验了 7 种 sticky 失效说法:3 种根本不成立
前端·javascript·程序员
我命由我1234513 小时前
Python 实用操作 - 文件操作(打开与关闭文件、读取文件、文件写入)
java·开发语言·前端·javascript·数据库·python·java-ee
Momo__14 小时前
你写的 import 重试,从来没生效过
前端·javascript·typescript
tryCbest15 小时前
Vue3——第 11 篇:组合式 API(上)——setup 与响应式 API 深度解析
前端·javascript·vue.js