golang – how to initialize a map field within a struct?

huangapple go评论86阅读模式
英文:

golang - how to initialize a map field within a struct?

问题

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

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

英文:

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.

答案1

得分: 50

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

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}
}
英文:

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

答案2

得分: 19

很常见的情况是代码(尤其是完全由你控制的代码)假设你正确初始化了数据结构。在这种情况下,通常会使用结构体字面量。

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

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

答案3

得分: 4

复合字面量在构造函数内部完全正常工作。通过使用初始问题来构造一个示例(并且天真地将 Vertices 的副本存储在映射中):

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

点击此处查看示例代码。

英文:

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

huangapple
  • 本文由 发表于 2014年12月19日 02:35:16
  • 转载请务必保留本文链接:https://go.coder-hub.com/27553399.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定