Golang – 常用设计 Singleton Pattern
Singleton的用意就是在proram运行期间Global只有1个实例,一旦创建了就无法重复被创建
【Mutex方式】
使用mutex, 防止并发创建instance
package main
import (
"fmt"
"sync"
)
// Instance 结构体表示单例实例,包含一个名称字段。
type Instance struct {
name string
}
// GlobalInstance 是指向单例实例的指针。
var GlobalInstance *Instance
// GlobalLock 用于同步对单例实例的访问。
var GlobalLock sync.Mutex
// getInstance 函数返回单例实例。如果实例不存在,则创建一个新实例。
func getInstance(instanceName string) *Instance {
// 检查实例是否已经存在
if GlobalInstance == nil {
// 获取锁以防止并发创建实例
GlobalLock.Lock()
defer GlobalLock.Unlock()
// 再次检查以确保实例仍为nil,以防止竞态条件
if GlobalInstance == nil {
GlobalInstance = &Instance{
name: instanceName,
}
}
}
return GlobalInstance
}
func main() {
// 获取单例实例
instance1 := getInstance("instance1")
instance2 := getInstance("instance2")
// 打印实例的名称
fmt.Println("instance1 名称:", instance1.name)
fmt.Println("instance2 名称:", instance2.name)
}
输出结果:
instance1 name: instance1
instance2 name: instance1
【Once.do 方式】
使用Once来保证 某个对象只会初始化一次,有一点要要注意的是 这个 once.Do 只会被运行一次,哪怕 Do 函数里面的发生了异常,对象初始化失败了,这个 Do 函数也不会被再次执行了
package main
import (
"fmt"
"sync"
)
var (
GlobalInstance *Instance // 全局单例变量
GlobalOnce sync.Once // 全局的 sync.Once 实例,确保单例只被初始化一次
)
type Instance struct {
name string // 单例实例的名称
}
// 获取单例实例的函数
func getInstance(instanceName string) *Instance {
// 如果全局单例变量为 nil,则进行初始化
if GlobalInstance == nil {
GlobalOnce.Do(func() {
// 使用 sync.Once 确保此处的初始化逻辑只会执行一次
GlobalInstance = &Instance{
name: instanceName, // 初始化单例实例的名称
}
})
}
return GlobalInstance // 返回单例实例
}
func main() {
instance1 := getInstance("instance1") // 获取第一个实例
instance2 := getInstance("instance2") // 获取第二个实例
fmt.Println("instance1 name:", instance1.name) // 打印第一个实例的名称
fmt.Println("instance2 name:", instance2.name) // 打印第二个实例的名称
}
输出结果:
instance1 name: instance1
instance2 name: instance1
Facebook评论