如何在Go结构中初始化成员

时间:2010-12-21 11:58:09

标签: new-operator 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")

此刻我得到一个零指针恐慌。

我通过使用另一个函数并在new()之后立即调用它来解决它:

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

但我想知道,如果可以摆脱这个样板初始化吗?

3 个答案:

答案 0 :(得分:65)

你只需要一个构造函数。常用的模式是

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

如果您的结构中有更多字段,可以在后端启动goroutine,或者注册终结器,可以在此构造函数中完成所有操作。

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

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

    go sm.backend()

    return &sm
}

答案 1 :(得分:9)

'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

答案 2 :(得分:5)

deamon很好的捕获。 Mue可能正在考虑将锁定为值而不是指针的更常见模式。由于Mutex的零值是即用型未锁定互斥锁,因此它不需要初始化,并且包含一个值,因为值很常见。作为进一步的简化,您可以通过省略字段名称来嵌入它。然后,您的结构获取Mutex的方法集。请参阅此工作示例http://play.golang.org/p/faO9six-Qx。我也拿出了推迟使用。在某种程度上,这是一个偏好和编码风格的问题,但由于它确实有一个小的开销,我倾向于不在小函数中使用它,特别是如果没有条件代码。