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