移動中のシングルトン
-
22-07-2019 - |
質問
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
}
パッケージを をシングルトンと考えるだけのhasan jの提案も参照してください。そして最後に、他の人が提案していることを考慮してください。シングルトンはしばしば問題のある実装の指標です。
他のヒント
曲がる方法を見つける前に、意志に沿って、いくつかの記事をご覧ください:
要約すると、時間の経過とともに人々はシングルトンが最適ではないことを発見し、テスト駆動開発を行おうとしている場合は特に :多くのレベルで、彼らはかなり悪いですグローバル変数。
[免責事項:あなたの質問に対する厳密な答えではないことは知っていますが、実際には関連性があります]
変数と関数をパッケージレベルで配置するだけです。
同様の質問もご覧ください: Pythonでシングルトンを作成する方法
同時世界では、これらの行がアトミックに実行されないことをもう少し認識する必要があると思います:
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
}
最良のアプローチは次のとおりです。
package singleton
import "sync"
type singleton struct {
}
var instance *singleton
var once sync.Once
func GetInstance() *singleton {
once.Do(func() {
instance = &singleton{}
})
return instance
}
このリンク
をお読みください1回パッケージを使用して初期化できます:
これにより、initメソッドが1回だけ呼び出されるようになります。
必要なオブジェクトの単一の静的、最終、定数、グローバル、アプリケーション全体のインスタンスがあるだけです。
ただし、これはオブジェクト指向のパラダイムと矛盾します。その使用は、可変オブジェクトではなく、プリミティブと不変オブジェクトに限定する必要があります。
Once.Do
はコードを1回だけ実行することに真剣であることを知っておく必要があります。つまり、パニックが発生している可能性がある場合でも、コードは常に 1回だけ実行されます。
https://golang.org/pkg/sync/#Once.Doからa>
f(注:かつてのロジック)がパニックになった場合、Doはそれが戻ったと見なします。今後のDoの呼び出しは、fを呼び出さずに戻ります。
この制限を克服するために、グローバル構成変数の一意の初期化を確保するために、代わりにミューテックスを使用しました: