go单例模式之懒汉模式
2020-01-05 本文已影响0人
CaiGuangyin
可以通过sync
包中的sync.Once
实现单例模式。
var once sync.Once
// 传入方法Do()中的函数只会被执行一次。
once.Do(func(){})
如下是once.go中的Do()
方法的源码:
func (o *Once) Do(f func()) {
if atomic.LoadUint32(&o.done) == 1 {
return
}
// Slow-path.
o.m.Lock()
defer o.m.Unlock()
if o.done == 0 {
defer atomic.StoreUint32(&o.done, 1)
f()
}
}
下面是用sync.Once
实现的单例模式
package main
import (
`fmt`
`sync`
)
type Singleton struct {}
var singleton *Singleton
var once sync.Once
func GetSingletonObj() *Singleton {
once.Do(func() {
fmt.Println("create singletonObj.")
singleton = new(Singleton)
})
return singleton
}
func main() {
var wg sync.WaitGroup
for i:=0;i<10;i++ {
wg.Add(1) // 往等待组中添加一个协程
go func() {
singleObj := GetSingletonObj()
// 打印singleObj的指针
fmt.Printf("singleObj mem addr: %p\n", singleObj)
wg.Done() // 协程执行完毕,会调用`wg.Add(-1)`将计数减1
}()
}
wg.Wait() // 等待所有协程执行完毕
}
sync.WaitGroup
的作用是让主函数main()
等待所有协程go func(){}
执行完后才退出。
输出的结果如下:
create singletonObj.
singleObj mem addr: 0x5851d0
singleObj mem addr: 0x5851d0
singleObj mem addr: 0x5851d0
singleObj mem addr: 0x5851d0
singleObj mem addr: 0x5851d0
singleObj mem addr: 0x5851d0
singleObj mem addr: 0x5851d0
singleObj mem addr: 0x5851d0
singleObj mem addr: 0x5851d0
singleObj mem addr: 0x5851d0
从输出结果可以看出,
create singletonObj
只被打印了一次,也就证明传入once.Do()
中的函数只被执行了一次,而GetSingletonObj()
只在第一次执行时会创建一个singleton
,后面每次执行返回的都是同一个singleton,从输出结果的singleObj mem addr
就可以看出来。