2010-12-21 76 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。我也拿出了延期的使用。在某種程度上,這是一個偏好和編碼風格的問題,但由於它具有小的開銷,我傾向於不使用它在小函數中,尤其是在沒有條件代碼的情況下。