web-dev-qa-db-fra.com

golang - comment initialiser un champ de carte dans une structure?

Je suis confus quant à la meilleure façon d'initialiser une structure qui contient une carte. L'exécution de ce code produit panic: runtime error: assignment to entry in nil map:

package main

type Vertex struct {
   label string
} 

type Graph struct {
  connections map[Vertex][]Vertex
} 

func main() {
  v1 := Vertex{"v1"}
  v2 := Vertex{"v2"}

  g := new(Graph)
  g.connections[v1] = append(g.coonections[v1], v2)
  g.connections[v2] = append(g.connections[v2], v1)
}

Une idée est de créer un constructeur, comme dans cette réponse .

Une autre idée est d'utiliser un add_connection méthode qui peut initialiser la carte si elle est vide:

func (g *Graph) add_connection(v1, v2 Vertex) {
  if g.connections == nil {
    g.connections = make(map[Vertex][]Vertex)
  }
  g.connections[v1] = append(g.connections[v1], v2)
  g.connections[v2] = append(g.connections[v2], v1)
}

Y a-t-il d'autres options? Je voulais juste voir s'il y avait une façon communément acceptée de le faire.

26
Matt

J'utiliserais probablement un constructeur pour faire ceci:

func NewGraph() *Graph {
    var g Graph
    g.connections = make(map[Vertex][]Vertex)
    return &g
}

J'ai trouvé cet exemple dans la norme image/jpeg package (pas avec une carte, mais avec une tranche):

type Alpha struct {
    Pix []uint8
    Stride int
    Rect Rectangle
}

func NewAlpha(r Rectangle) *Alpha {
    w, h := r.Dx(), r.Dy()
    pix := make([]uint8, 1*w*h)
    return &Alpha{pix, 1 * w, r}
}
35
julienc

Il est très courant que le code (en particulier le code entièrement sous votre contrôle) suppose que vous initialisez correctement la structure de données. Un littéral struct est généralement utilisé dans ce cas

g := &Graph{
    connections: make(map[Vertex][]Vertex),
}
13
JimB

Les littéraux composites fonctionnent très bien à l'intérieur d'un constructeur. Création d'un exemple à l'aide de la question initiale (et stockage naïf de copies de sommets dans la carte):

func NewGraph(v1 Vertex, v2 Vertex) *Graph {
    return &Graph{ map[Vertex][]Vertex{ v1: []Vertex{v2}, v2: []Vertex{v1} }}
}

func main() {
  v1 := Vertex{"v1"}
  v2 := Vertex{"v2"}

  g := NewGraph(v1, v2)
  fmt.Println(g)
}

https://play.golang.org/p/Lf4Gomp4tJ

2
durp