web-dev-qa-db-fra.com

Comment initialiser des membres dans la structure Go

Je suis nouveau à Golang, donc l'allocation me rend fou:

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
}

et plus tard, j'appelle juste:

sm := new(SyncMap)
sm.Put("Test, "Test")

À ce moment, je reçois une panique de pointeur nul.

J'ai travaillé autour d'elle en utilisant une autre fonction et en l'appelant juste après new():

func (m *SyncMap) Init() {
        m.hm = make(map[string]string)
        m.lock = new(sync.RWMutex)
}

Mais je me demande, s'il est possible de se débarrasser de cette initialisation passe-partout?

54
Illarion Kovalchuk

Vous avez juste besoin d'un constructeur. Un modèle couramment utilisé est

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

En cas de plus de champs à l'intérieur de votre structure, démarrer un goroutine en tant que backend, ou enregistrer un finaliseur, tout pourrait être fait dans ce constructeur.

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

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

    go sm.backend()

    return &sm
}
66
themue

La solution de 'Mue' ne fonctionne pas car le mutex n'est pas initialisé. La modification suivante fonctionne:

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

9
deamon

Bonne prise par le démon. Mue pensait peut-être au modèle le plus courant d'inclure le verrou en tant que valeur plutôt qu'en tant que pointeur. Étant donné que la valeur zéro d'un Mutex est un Mutex déverrouillé prêt à l'emploi, il ne nécessite aucune initialisation et en inclure un comme valeur est commun. Pour simplifier davantage, vous pouvez l'intégrer en omettant le nom du champ. Votre structure acquiert alors l'ensemble de méthodes du Mutex. Voir cet exemple de travail, http://play.golang.org/p/faO9six-Qx . J'ai également retiré l'utilisation du report. Dans une certaine mesure, c'est une question de préférence et de style de codage, mais comme il a une petite surcharge, j'ai tendance à ne pas l'utiliser dans de petites fonctions, surtout s'il n'y a pas de code conditionnel.

5
Sonia