乐趣区

GO 单例模式

单例模式是常用的模式之一,一般介绍的单例模式有 饿汉式 和 懒汉式 等,不管那种模式最终目的只有一个,就是值实例化一次,只允许一个实例存在。
GO 语言实现单例模式相对简单,这里考虑到并发,用到了 sync.Mutex 和结构体 sync.Once。
示例:
package main

import (
“fmt”
“sync”
)

var (
lock *sync.Mutex = &sync.Mutex{}
instance *Singleton
)
type Singleton struct {
}

func GetInstance() *Singleton {
if instance == nil {
lock.Lock()
defer lock.Unlock()
if instance == nil {
instance = &Singleton{}
fmt.Println(“instance…”)
}
}
return instance
}

func main() {
var s *Singleton
s = GetInstance()
s = GetInstance()
fmt.Println(s)
}
执行结果:
instance…&{}
通过结果可以看到只输出了一个 instance…。
上面的实现方式还可以通过结构体 sync.Once 更优雅的实现。
示例:
package main

import (
“fmt”
“sync”
)

var (
once sync.Once
instance *Singleton
)

type Singleton struct {
}

func GetInstance() *Singleton {
once.Do(func() {
instance = &Singleton{}
fmt.Println(“instance…”)
})
return instance
}

func main() {
var s *Singleton
s = GetInstance()
s = GetInstance()
fmt.Println(s)
}
输出结果:
instance…&{}
通过 sync.Once 的源代码查看它是如何运行的
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.Do(f func()) 使用加锁原子操作(代码包 sync/atomic)来保证函数 f 只执行一次。
目录

退出移动版