Goプログラミング言語でシングルトンデザインパターンをどのように実装しますか?
シングルトンパターンを実装するかどうかの引数を別にしておくのは良い考えです。可能な実装は次のとおりです。
_package singleton
type single struct {
O interface{};
}
var instantiated *single = nil
func New() *single {
if instantiated == nil {
instantiated = new(single);
}
return instantiated;
}
_
single
とinstantiated
はプライベートですが、New()
はパブリックです。したがって、New()
を経由せずにsingle
を直接インスタンス化することはできず、プライベートブール値instantiated
を使用してインスタンス化の数を追跡します。 single
の定義を好みに合わせて調整してください。
ただし、他にもいくつかの noted があるため、init()
でシングルトンを初期化するだけでない限り、これはスレッドセーフではありません。より良い方法は、_sync.Once
_を利用してハードワークを実行することです。
_package singleton
import "sync"
type single struct {
O interface{};
}
var instantiated *single
var once sync.Once
func New() *single {
once.Do(func() {
instantiated = &single{}
})
return instantiated
}
_
また、パッケージをasシングルトンと考えるだけのhasan jの提案も参照してください。そして最後に、他の人が示唆していることを考慮してください。シングルトンはしばしば問題のある実装の指標です。
曲がる方法を見つける前に、思い通りに、いくつかの記事を見てみましょう。
要約すると、時間が経つにつれて人々はシングルトンが最適ではないことを発見し、テスト駆動型の開発を試みようとしている場合は、imho特に:多くのレベルはグローバル変数と同じくらい悪いです。
[免責事項:私はあなたの質問に対する厳密な回答ではないことを知っていますが、それは本当に関連しています]
変数と関数をパッケージレベルで配置するだけです。
同様の質問も参照してください: Pythonでシングルトンを作成する方法
最善のアプローチは次のとおりです。
package singleton
import "sync"
type singleton struct {
}
var instance *singleton
var once sync.Once
func GetInstance() *singleton {
once.Do(func() {
instance = &singleton{}
})
return instance
}
あなたはこれを読むべきです Link
once package を使用して初期化を行うことができます:
これにより、initメソッドが1回だけ呼び出されることが保証されます。
次のコードでわかるように、簡単な方法です。
package main
import (
"fmt"
"sync"
)
type singleton struct {
count int
sync.RWMutex
}
var instance singleton
func GetInstance() *singleton {
return &instance
}
func (s *singleton) AddOne() {
s.Lock()
defer s.Unlock()
s.count++
}
func (s *singleton) GetCount() int {
s.RLock()
defer s.RUnlock()
return s.count
}
func main() {
obj1 := GetInstance()
obj1.AddOne()
fmt.Println(obj1.GetCount())
obj2 := GetInstance()
obj2.AddOne()
fmt.Println(obj2.GetCount())
obj3 := GetInstance()
obj3.AddOne()
fmt.Println(obj3.GetCount())
}
期待される結果は次のとおりです。
1 2 3
同じリソースにアクセスしているからです。これが、複数のプロセスからの同時アクセスcount属性を証明するためにミューテックスを追加した理由です。 :-)
ソース:
必要なオブジェクトの単一の静的な最終的な定数のグローバルなアプリケーション全体のインスタンスがあるだけです。
ただし、これはOOパラダイムとは矛盾します。その使用は、可変オブジェクトではなく、プリミティブおよび不変オブジェクトに限定する必要があります。
Once.Do
は、コードを1回だけ実行することを真剣に考えています。つまり、パニックが発生したとしても、コードはalwaysが1回だけ実行されます。
から https://golang.org/pkg/sync/#Once.Do
F(注:かつてのロジック)でパニックが発生した場合、Doはそれが戻ったと見なします。 Doの今後の呼び出しは、fを呼び出さずに戻ります。
代わりにmutexを使用して、グローバル構成変数の一意の初期化を確実にし、この制限を克服しました。