Подтвердить что ты не робот

Как инициализировать элементы в структуре 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)
}

Но мне интересно, можно ли избавиться от этой инициализации шаблона?

4b9b3361

Ответ 1

Вам просто нужен конструктор. Общим использованным шаблоном является

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

Если в вашей структуре больше полей, начиная с goroutine в качестве backend или регистрируя финализатор, все это можно сделать в этом конструкторе.

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

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

    go sm.backend()

    return &sm
}

Ответ 2

Решение "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

Ответ 3

Хороший улов от деамона. Мью, возможно, думал о более распространенной схеме включения блокировки как значения, а не указателя. Поскольку нулевое значение Mutex является готовым к использованию разблокированным Mutex, оно не требует инициализации и включает в себя одно значение, которое является общим. В качестве дальнейшего упрощения вы можете вставить его, опуская имя поля. Затем ваша структура получает набор методов Mutex. См. Этот рабочий пример, http://play.golang.org/p/faO9six-Qx. Также я взял использование отсрочки. В какой-то степени это вопрос предпочтения и стиля кодирования, но поскольку он имеет небольшие накладные расходы, я стараюсь не использовать его в небольших функциях, особенно если нет условного кода.