I am new to Golang so allocation in it makes me insane:
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
}
and later, I just call:
sm := new(SyncMap)
sm.Put("Test, "Test")
At this moment I get a nil pointer panic.开发者_如何学编程
I've worked around it by using another one function, and calling it right after new()
:
func (m *SyncMap) Init() {
m.hm = make(map[string]string)
m.lock = new(sync.RWMutex)
}
But I wonder, if it's possible to get rid of this boilerplate initializing?
You just need a constructor. A common used pattern is
func NewSyncMap() *SyncMap {
return &SyncMap{hm: make(map[string]string)}
}
In case of more fields inside your struct, starting a goroutine as backend, or registering a finalizer everything could be done in this constructor.
func NewSyncMap() *SyncMap {
sm := SyncMap{
hm: make(map[string]string),
foo: "Bar",
}
runtime.SetFinalizer(sm, (*SyncMap).stop)
go sm.backend()
return &sm
}
The solution of 'Mue' doesn't work since the mutex is not initialized. The following modification works:
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
Good catch by deamon. Mue was possibly thinking of the more common pattern of including the lock as a value rather than a pointer. Since the zero value of a Mutex is a ready-to-use unlocked Mutex, it requires no initialization and including one as a value is common. As a further simplification, you can embed it by omitting the field name. Your struct then acquires the method set of the Mutex. See this working example, http://play.golang.org/p/faO9six-Qx. Also I took out the use of defer. To some extent it's a matter of preference and coding style, but since it does have a small overhead, I tend not to use it in small functions, especially if there is no conditional code.
精彩评论