This is a creation in Article, where the information may have evolved or changed.
Singleton mode is a kind of common software design pattern. In its core structure, it contains only a special class called a singleton class. The singleton mode can ensure that there is only one instance of a class in the system, and the instance is easy to be accessed by the outside world, thus it is convenient to control the number of instances and save system resources. Singleton mode is the best solution if you want to have only one object for a class in the system.
1.Go implementation of a non-thread-safe Singleton mode (lazy is the idle single-case haha):
Package <textarea wrap="soft" class="crayon-plain print-no" data-settings="dblclick" readonly="" style="-moz-tab-size:4; -o-tab-size:4; -webkit-tab-size:4; tab-size:4; font-size: 12px !important; line-height: 15px !important;">Singletontype Singleton struct {}var instance *singletonfunc getinstance () *singleton {If instance = nil {ins tance = &singleton{}//<---Not THREAD safe}return instance}</textarea>
| 12345678910111213 |
Package Singletontype Singleton struct {}var instance *Singletonfuncgetinstance() *Singleton {if instance == Nil {instance = &Singleton{} //<---not THREAD SAFE}return instance} |
The non-thread-safe singleton pattern is one of the most widely used. Many of the open source projects on GitHub use non-threaded security.
This type of lazy loading is obvious, but the fatal is that the multithreading does not work properly.
2.Go implementation of a single-case mode with a thread lock
<textarea wrap="soft" class="crayon-plain print-no" data-settings="dblclick" readonly="" style="-moz-tab-size:4; -o-tab-size:4; -webkit-tab-size:4; tab-size:4; font-size: 12px !important; line-height: 15px !important;">var mu sync.mutexfunc getinstance () *singleton {mu. Lock ()//<---Unnecessary locking if instance already created defer MU. Unlock () If instance = = Nil {instance = &singleton{}} return instance}</textarea>
| 1234567891011 |
var muSync.Mutexfuncgetinstance() *Singleton { mu.Lock() //<---Unnecessary locking if instance already created defermu.Unlock() if instance == Nil { instance = &Singleton{} } return instance} |
Here's the go.
<textarea wrap="soft" class="crayon-plain print-no" data-settings="dblclick" readonly="" style="-moz-tab-size:4; -o-tab-size:4; -webkit-tab-size:4; tab-size:4; font-size: 12px !important; line-height: 15px !important;">Sync.mutex</textarea>
Sync/mutex is one of the underlying basic objects of the go language, used to build synchronization logic between multiple goroutine, and is therefore used by a large number of high-level objects.
Its working model is similar to the Linux kernel Futex object, the implementation is very concise, performance is guaranteed.
The mutex object has only two numeric fields, divided into state (stored states) and SEMA (the amount of semaphores used to calculate the number of sleep goroutine).
The 0 value that is filled in during initialization sets the mutex to an unlocked state, while guaranteeing minimal time overhead.
This feature allows the mutex to be used as a sub-object of other objects.
3. Single-case mode with check lock
<textarea wrap="soft" class="crayon-plain print-no" data-settings="dblclick" readonly="" style="-moz-tab-size:4; -o-tab-size:4; -webkit-tab-size:4; tab-size:4; font-size: 12px !important; line-height: 15px !important;">func getinstance () *singleton {if instance = = Nil {//<--not yet perfect. Since it's not fully atomic Mu. Lock () defer MU. Unlock () If instance = = Nil {instance = &singleton{}}} return instance}</textarea>
| 1234567891011 |
funcgetinstance() *Singleton { if instance == Nil { //<--not yet perfect. Since it's not fully atomic mu.Lock() defermu.Unlock() if instance == Nil { instance = &Singleton{} } } return instance} |
It's a good way, but it's not perfect. Because compiler optimizations do not check the instance store state. If you use the Sync/atomic package, you can automatically load and set the tag for us.
<textarea wrap="soft" class="crayon-plain print-no" data-settings="dblclick" readonly="" style="-moz-tab-size:4; -o-tab-size:4; -webkit-tab-size:4; tab-size:4; font-size: 12px !important; line-height: 15px !important;">import "Sync" import "Sync/atomic" var initialized uint32...func getinstance () *singleton {if atomic. LoadUInt32 (&initialized) = = 1 {return instance} mu. Lock () defer MU. Unlock () if initialized = = 0 {instance = &singleton{} atomic. StoreUint32 (&initialized, 1)} return instance}</textarea>
| 12345678910111213141516171819202122 |
Import "Sync"Import "Sync/atomic"var initializedUInt32...funcgetinstance() *Singleton { if Atomic.LoadUInt32(&initialized) == 1 {return instance} mu.Lock() defermu.Unlock() if initialized == 0 { instance = &Singleton{} Atomic.StoreUint32(&initialized, 1) } return instance} |
Personally think that a better use of a single case in Go is this
Package <textarea wrap="soft" class="crayon-plain print-no" data-settings="dblclick" readonly="" style="-moz-tab-size:4; -o-tab-size:4; -webkit-tab-size:4; tab-size:4; font-size: 12px !important; line-height: 15px !important;">singletonimport ("Sync") type singleton struct {}var instance *singletonvar once sync. Oncefunc getinstance () *singleton {once. Do (func () {instance = &singleton{}}) return instance}</textarea>
| 123456789101112131415161718 |
Package SingletonImport ( "Sync")type Singleton struct {}var instance *Singletonvar onceSync.Once funcgetinstance() *Singleton { once. Do(func() { instance = &Singleton{} }) return instance} |
By using Sync. The Once package enables thread-safe singleton mode.
If there is something wrong with the writing, the place welcomes the point.
single-case mode for Go