2017-10-03 16 views
0

私はJavaから来て、Goの型システムの仕組みを理解するのに苦労しています。私は単純なグラフのデータ構造を作成し、幅広い最初の検索を実装したいと思います。これはこれまで私が持っていたものです。golang構造体のプロパティが変更されない

package graph 

import "fmt" 

type Node struct { 
    neighbors []Edge 
    visited bool 
    name  string 
} 

type Edge struct { 
    neighbor Node 
} 

type Graph struct { 
    nodes []Node 
} 

func (g *Graph) addNode(node Node) { 
    g.nodes = append(g.nodes, node) 
} 

func (n *Node) addEdge(neighbor Node) { 
    edge := Edge{ 
     neighbor: neighbor, 
    } 
    n.neighbors = append(n.neighbors, edge) 
} 

func (g Graph) String() { 
    for _, node := range g.nodes { 
     //fmt.Printf("nodename: %v", node.name) 
     fmt.Println(len(node.neighbors)) 
     if len(node.neighbors) > 0 { 
      fmt.Print("node: %v, edges: ", node.name) 
      for _, e := range node.neighbors { 
       fmt.Print(e.neighbor.name) 
      } 
     } 
    } 
} 

私はテストコードでそれを実行しよう:私の文字列で

func TestGraph(t *testing.T) { 
    graph := Graph{} 
    n1 := Node { name: "abc", } 
    n2 := Node { name: "def", } 
    graph.addNode(n1) 
    graph.addNode(n2) 
    n1.addEdge(n2) 

    graph.String() 
} 

()メソッドを、LEN(node.neighborsは)私が間違っているのは何常に0ですか?私はaddEdgeで参照型を取ったので、ノード参照を変更すると思ったが、私は明らかにGoの型システムについて何か不足している。前もって感謝します!

+1

FWIW '文字列(作成される)' '通常fmt.Stringer'(https://golang.org/pkg/fmt/#Stringer)インタフェースを満たす方法'文字列()STRING'あります。ほとんどのGoプログラマは、 'string'を返さない' String() 'を見て驚くでしょう。 –

答えて

3

これは型システムの問題ではありませんが、Goでのデータの受け渡し方法の問題です。

私は、根本的な誤解は「参照渡し」に関するものだと思います。ゴーでは、すべてが値によって渡され、何のパスを参照してありません(https://golang.org/doc/faq#pass_by_value

あなたはaddEdgeメソッドにNode構造体を渡すときに、それは実際にその構造体のコピーを作っています。

同じ基本構造体をコピーする代わりに参照したい場合は、それにポインタを渡す必要があります。あなたはポインタか、新しい値によって、あなたの変数を渡す必要があり

package main 

import "fmt" 

type Node struct { 
    neighbors []*Edge 
    visited bool 
    name  string 
} 

type Edge struct { 
    neighbor *Node 
} 

type Graph struct { 
    nodes []*Node 
} 

func (g *Graph) addNode(node *Node) { 
    g.nodes = append(g.nodes, node) 
} 

func (n *Node) addEdge(neighbor *Node) { 
    edge := &Edge{ 
     neighbor: neighbor, 
    } 
    n.neighbors = append(n.neighbors, edge) 
} 

func (g Graph) String() { 
    for _, node := range g.nodes { 
     //fmt.Printf("nodename: %v", node.name) 
     fmt.Printf("number of neighbors: %d\n", len(node.neighbors)) 
     if len(node.neighbors) > 0 { 
      fmt.Printf("node: %v, edges: ", node.name) 
      for _, e := range node.neighbors { 
       fmt.Printf("%q", e.neighbor.name) 
      } 
      fmt.Println() 
     } 
    } 
} 

func main() { 
    graph := &Graph{} 
    n1 := &Node{name: "abc"} 
    n2 := &Node{name: "def"} 
    graph.addNode(n1) 
    graph.addNode(n2) 
    n1.addEdge(n2) 

    graph.String() 
} 
1

を:(https://play.golang.org/p/Qsbi4LBXS4をあなたが微調整することができ、ここでコードを実行します。)

構造体を渡すためにポインタを使用して、次のわずかに変更されたコードを、試してみてください

func (g *Graph) addNode(node *Node) { 
    g.nodes = append(g.nodes, node) 
} 

... 
n1 := Node { name: "abc", } 
graph.addNode(&n1) 
... 
n1.addEdge(&n2) 
関連する問題