Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to initialize members in Go struct

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?

like image 741
Illarion Kovalchuk Avatar asked Dec 21 '10 11:12

Illarion Kovalchuk


2 Answers

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 } 
like image 116
themue Avatar answered Oct 20 '22 08:10

themue


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

like image 45
deamon Avatar answered Oct 20 '22 09:10

deamon