Go 構造体の割り当てと初期化は、初心者にとって難しい場合があります。次の例を考えてみましょう。
import "sync" type SyncMap struct { lock *sync.RWMutex hm map[string]string } func (m *SyncMap) Put(k, v string) { m.lock.Lock() defer m.lock.Unlock() m.hm[k] = v } func main() { sm := new(SyncMap) sm.Put("Test", "Test") }
ロックと hm が初期化されていないため、このコードは nil ポインタ例外でパニックになります。
これに対処するには、次の回避策を使用できます。
func (m *SyncMap) Init() { m.hm = make(map[string]string) m.lock = new(sync.RWMutex) } func main() { sm := new(SyncMap) sm.Init() sm.Put("Test", "Test") }
しかし、これにより不必要な定型文が追加されます。
よりクリーンなアプローチは、コンストラクター関数を使用して構造体を初期化することです。コンストラクターは、構造体の初期化されたインスタンスを返す関数です。例:
func NewSyncMap() *SyncMap { return &SyncMap{hm: make(map[string]string)} }
このコンストラクターは hm フィールドを初期化し、新しく作成された SyncMap インスタンスへのポインターを返します。
func main() { sm := NewSyncMap() sm.Put("Test", "Test") }
これで、コードはボイラープレートなしで構造体を正しく初期化します。 .
コンストラクター パターンは、複数のフィールドの初期化、ゴルーチンの開始、または登録にも使用できます。構造体のファイナライザー。例:
func NewSyncMap() *SyncMap { sm := SyncMap{ hm: make(map[string]string), foo: "Bar", } runtime.SetFinalizer(sm, (*SyncMap).stop) go sm.backend() return &sm }
このコンストラクターは、hm フィールドと foo フィールドの両方を初期化し、backend() のゴルーチンを開始し、SyncMap インスタンスがガベージ コレクションされたときに stop() メソッドを実行するファイナライザーを登録します。
以上がコンストラクター パターンは Go 構造体の初期化問題をどのように解決できますか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。