Go语言 - 如何在结构体中初始化一个map字段?

45

我对包含映射的结构体初始化的最佳方法感到困惑。运行这段代码会产生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)
}

一个想法是创建一个构造函数,例如这个答案中所示。

另一个想法是使用add_connection方法,如果地图为空,则可以初始化它:

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

还有其他选项吗?只是想知道是否有一种通常被接受的方法来做到这一点。


3
构造函数是除了假设程序员可以独立完成之外,通常被接受的方式。 - JimB
可能是如何在Go结构中初始化成员的重复问题。 - JimB
3个回答

51

我可能会使用构造函数来完成这个任务:

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

我在标准的image/jpeg包中找到了这个例子(没有使用map,而是使用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}
}

4
非常感谢你在标准库中找到这个例子,这确实增强了信心。 - Matt

19

对于代码(特别是完全受控制的代码)假定你正确地初始化了数据结构是非常普遍的。在这种情况下,通常使用结构体字面量。

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

5
你如何用特定的值来初始化连接值? - lostboy_19

4

复合文字在构造函数中完美运作。可以通过以下示例来解释(并且在地图中天真地存储顶点的副本):

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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接