46

I'm confused about the best way to initialize a struct that contains a map. Running this code produces 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)
}

One idea is to create a constructor, as in this answer.

Another idea is to use an add_connection method that can initialize the map if it's empty:

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)
}

Are there other options? Just wanted to see if there is a commonly-accepted way to do this.

2
  • 3
    A constructor is the commonly accepted way (other than assuming the programer can do it unassisted) Commented Dec 18, 2014 at 18:37
  • possible duplicate of how to initialize members in go struct Commented Dec 18, 2014 at 18:50

3 Answers 3

53

I would probably use a constructor to do this:

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

I've found this example in the standard image/jpeg package (not with a map though, but with a slice):

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}
}
Sign up to request clarification or add additional context in comments.

1 Comment

great, thanks for finding the example in the standard lib, that definitely inspires confidence
20

It's very common for code (especially code fully under your control) to assume you initialize the data structure correctly. A struct literal is usually used in this case

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

1 Comment

But how do you initialize the connections value with some particular value?
4

Composite literals work just fine inside a constructor. Contriving an example using the initial question (and naively storing copies of Vertices in the map):

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

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.