GOシングルモード


単例モードはよく用いられるモードの1つであり、一般に紹介される単例モードは などであり、そのモードの最終目的が1つであっても、一度だけインスタンス化され、1つのインスタンスのみが存在することを許容する.
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が1つしか出力されていないことがわかります....
以上の実施形態は、構造体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()は、関数fが一度だけ実行されることを保証するために、ロック原子操作(コードパケットsync/atomic)を使用する.
  • ディレクトリ