2014-12-18 14 views
19

Nie mam pojęcia, jak najlepiej zainicjować strukturę zawierającą mapę. Uruchomienie tego kodu produkuje panic: runtime error: assignment to entry in nil map:golang - jak zainicjować pole mapy w strukturze?

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

Jednym z pomysłów jest utworzenie konstruktora, jak w this answer.

Innym pomysłem jest użycie metody add_connection które mogą zainicjować mapę jeśli jest pusty:

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

Czy istnieją inne opcje? Chciałem tylko sprawdzić, czy istnieje powszechnie akceptowany sposób na zrobienie tego.

+2

Konstruktor jest powszechnie akceptowany sposób (inne niż zakładając programer może to zrobić bez pomocy) – JimB

+0

możliwe duplikat [jak zainicjować członków w go struct] (http://stackoverflow.com/questions/4498998/how-to-initialize-members-in-go-struct) – JimB

Odpowiedz

28

I pewnie użyć konstruktora, aby to zrobić:

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

Znalazłem ten przykład w standardowym image/jpeg pakietu (nie z mapą chociaż , ale z plasterkiem):

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

świetnie, dziękuję za znalezienie przykładu w standardowej bibliotece, która zdecydowanie budzi zaufanie – Matt

13

Bardzo często kod (szczególnie kod w pełni kontrolowany) zakłada, że ​​poprawnie zainicjalizowano strukturę danych. Struct dosłowny jest zwykle stosowany w tym przypadku

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

Ale jak zainicjalizować wartość połączeń z konkretnymi wartość? –

1

Literały kompozytowe działają dobrze wewnątrz konstruktora. Contriving przykład przy użyciu początkowego pytanie (i naiwnie przechowywania kopii wierzchołków na mapie):

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