Как инициализировать элементы в Go struct
Я новичок в 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 ответа:
вам просто нужен конструктор. Обычно используется шаблон
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 }
решение '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") }
хороший улов от deamon. Mue, возможно, думал о более распространенном шаблоне включения блокировки в качестве значения, а не указателя. Поскольку нулевое значение мьютекса является готовым к использованию разблокированным мьютексом, он не требует инициализации и включает его в качестве значения. В качестве дальнейшего упрощения вы можете внедрить его, опустив имя поля. Затем ваша структура получает набор методов мьютекса. См. этот рабочий пример,http://play.golang.org/p/faO9six-Qx. Также я вынул использование отсрочки. В какой-то степени это вопрос предпочтения и стиля кодирования, но поскольку он имеет небольшие накладные расходы, я не склонен использовать его в небольших функциях, особенно если нет условного кода.