2010-12-21 80 views
50

我是新来Golang所以它分配让我疯狂:在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, true 
} 

后来,我只要致电:

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

在这一刻,我收到了零指针恐慌。

我用另外一个功能,并要求它周围的工作new()之后:

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

但我不知道,如果有可能摆脱这个样板初始化的?

回答

63

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

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

非常感谢!现在我记得,在教程中有一些关于构造函数的内容,但作为一个Java开发人员,我认为它应该与new运算符有关,而不是New ...代码约定 – 2010-12-21 13:00:05

+1

这会起作用,但不是最好的建议。 RWMutex应作为一个值包含在内,而不是指针。它的零值是一个随时可以使用的互斥体,这样就可以避免显式的构造函数。 – kelnos 2013-01-13 01:22:50

+0

应该采取不同的名称,因为它只是一个例子。正如你将会看到的,我还初始化了不是原始结构的一部分的字段'foo'。 ;) – Mue 2013-01-14 10:49:50

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

+0

为什么要使用指向'sync.RWMutex'的指针? – Danilo 2015-11-24 13:00:53

+0

非常感谢!未初始化的互斥造成一个非常难以调试的细微错误。对Lock()和Unlock()的调用成功,但访问不同步。 – Steve 2017-05-12 06:33:24

5

良好的渔获物。 Mue可能会考虑将锁定作为一个值而不是指针的更常见模式。由于Mutex的零值是一个随时可用的解锁Mutex,因此它不需要初始化,并且包含一个值作为常见值。作为进一步简化,您可以通过省略字段名称来嵌入它。您的结构然后获取互斥体的方法集。看到这个工作示例,http://play.golang.org/p/faO9six-Qx。我也拿出了延期的使用。在某种程度上,这是一个偏好和编码风格的问题,但由于它具有小的开销,我倾向于不使用它在小函数中,尤其是在没有条件代码的情况下。