How to initialize members in Go struct

Illarion Kovalchuk picture Illarion Kovalchuk · Dec 21, 2010 · Viewed 61.1k times · Source

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?

Answer

themue picture themue · Dec 21, 2010

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
}