web-dev-qa-db-ja.com

Go構造体でメンバーを初期化する方法

私はGolangを初めて使用するので、その中に割り振ると非常識になります。

_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, true
}
_

その後、私は電話するだけです:

_sm := new(SyncMap)
sm.Put("Test, "Test")
_

この瞬間、私はゼロのポインタパニックを取得します。

別の1つの関数を使用して、new()の直後に呼び出して回避しました。

_func (m *SyncMap) Init() {
        m.hm = make(map[string]string)
        m.lock = new(sync.RWMutex)
}
_

しかし、この定型的な初期化を取り除くことができるのだろうか?

54

あなただけのコンストラクタが必要です。一般的に使用されるパターンは

func NewSyncMap() *SyncMap {
    return &SyncMap{hm: make(map[string]string)}
}

構造体内にフィールドがさらにある場合、ゴルーチンをバックエンドとして開始するか、ファイナライザを登録することで、このコンストラクタですべてを実行できます。

func NewSyncMap() *SyncMap {
    sm := SyncMap{
        hm: make(map[string]string),
        foo: "Bar",
    }

    runtime.SetFinalizer(sm, (*SyncMap).stop)

    go sm.backend()

    return &sm
}
66
themue

ミューテックスが初期化されていないため、「Mue」のソリューションは機能しません。次の変更が機能します。

package main

import "sync"

type SyncMap struct {
        lock *sync.RWMutex
        hm map[string]string
}

func NewSyncMap() *SyncMap {
        return &SyncMap{lock: new(sync.RWMutex), hm: make(map[string]string)}
}

func (m *SyncMap) Put (k, v string) {
        m.lock.Lock()
        defer m.lock.Unlock()
        m.hm[k] = v
}

func main() {
    sm := NewSyncMap()
    sm.Put("Test", "Test")
}

http://play.golang.org/p/n-jQKWtEy5

9
deamon

デーモンによる良いキャッチ。 Mueはおそらく、ロックをポインターではなく値として含める一般的なパターンを考えていました。 Mutexのゼロ値は、すぐに使用できるロック解除されたMutexであるため、初期化を必要とせず、値として1を含めるのが一般的です。さらに簡略化するために、フィールド名を省略して埋め込むことができます。構造体は、Mutexのメソッドセットを取得します。この実例 http://play.golang.org/p/faO9six-Qx を参照してください。また、私は延期の使用を取り出しました。ある程度は好みとコーディングスタイルの問題ですが、オーバーヘッドが小さいため、特に条件付きコードがない場合は小さな関数で使用する傾向はありません。

5
Sonia