單例模式是經常使用的模式之一,通常介紹的單例模式有 餓漢式
和 懶漢式
等,無論那種模式最終目的只有一個,就是隻實例化一次,僅容許一個實例存在。git
GO語言實現單例模式相對簡單,這裏考慮到併發,用到了sync.Mutex 和結構體sync.Once。github
示例:golang
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...。atom
上面的實現方式還能夠經過結構體sync.Once更優雅的實現。code
示例:get
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) }
輸出結果:it
instance...
&{}ast
經過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 只執行一次。