goプログラミング言語でSingletonデザインパターンをどのように実装しますか?
10 に答える
シングルトン パターンの実装が良いアイデアかどうかの議論はさておき、考えられる実装は次のとおりです。
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()
です。single
したがって、 を介さずに直接インスタンス化することはできずNew()
、プライベート ブール値でインスタンス化の数を追跡しますinstantiated
。single
の定義を好みに合わせて調整します。
ただし、他の何人かが指摘しているように、シングルトンを初期化するだけでない限り、これはスレッドセーフではありません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
}
パッケージをシングルトンと考えるだけの hasan j の提案も参照してください。そして最後に、他の人が示唆していることを考慮してください。シングルトンは多くの場合、問題のある実装の指標であるということです。
同時実行の世界では、これらの行がアトミックに実行されないことにもう少し注意する必要があると思います。
if instantiated == nil {
instantiated = new(single);
}
@marketerの提案に従い、パッケージ「sync」を使用します
import "sync"
type MySingleton struct {
}
var _init_ctx sync.Once
var _instance *MySingleton
func New() * MySingleton {
_init_ctx.Do( func () { _instance = new(MySingleton) } )
return _instance
}
変数と関数をパッケージ レベルに置くだけです。
同様の質問も参照してください: Python でシングルトンを作成する方法
曲げる方法を見つけようとする前に、自分の意思で行ってください。次の記事を参照してください。
要約すると、時間の経過とともに、人々はシングルトンが最適ではないことに気付きました。特に、テスト駆動型開発を行おうとしている場合はそうです。多くのレベルで、シングルトンはグローバル変数とほぼ同じくらい悪いです。
[免責事項: あなたの質問に対する厳密な回答ではないことは承知していますが、実際には関連性があります]
once パッケージを使用して初期化を行うことができます。
これにより、init メソッドが 1 回だけ呼び出されるようになります。
必要なオブジェクトの単一の静的、最終、定数、グローバル、アプリケーション全体のインスタンスを用意するだけです。
ただし、これは OO パラダイムと矛盾します。その使用は、可変オブジェクトではなく、プリミティブと不変オブジェクトに制限する必要があります。
Once.Do
は、コードを 1 回だけ実行することに真剣に取り組んでいることに注意してください。つまり、パニックに陥った可能性がある場合でも、コードは常に1 回だけ実行されます。
https://golang.org/pkg/sync/#Once.Doから
f (注: once ロジック) がパニックした場合、Do はそれが戻ったと見なします。今後の Do の呼び出しは、f を呼び出さずに戻ります。
この制限を克服するために、代わりにミューテックスを使用して、グローバル構成変数の一意の初期化を保証しました。