2017-02-05 23 views
-1

私は、頭の中で頭の中を囲むようにしています。私はなぜ私のInsertList方法は、すべての構造体のメソッドの構造体のポインタ値を変更します。

で異なる構造体へのノードのポインタを参照していませんでした node = &newHeadであることを理解したいと思います私は

package main 

import (
    "fmt" 
) 

// LinkedList type 
type LinkedList struct { 
    data int 
    next *LinkedList 
} 

// InsertList will insert a item into the list 
func (node *LinkedList) InsertList(data int) { 
    newHead := LinkedList{data, node} 
    node = &newHead 
} 

func main() { 
    node := &LinkedList{} 
    node.InsertList(4) 
    fmt.Printf("node = %+v\n", node) 
} 

右ここにこのコードを持っており、出力は

node = &{data:0 next:<nil>} 

です

答えて

3

受信者nodeは、他のパラメータと同じように値渡されるため、関数内で行った変更は呼び出し元には表示されません。関数の外に存在するものを変更する関数が必要な場合、関数はそのオブジェクトへのポインタを扱う必要があります。あなたのケースでは、nodeはポインタですが、本当に必要なのは、リスト自体を表す何かへのポインタです。たとえば、このようなことの

package main 

import (
    "fmt" 
) 

type LinkedListNode struct { 
    data int 
    next *LinkedListNode 
} 

type LinkedList struct { 
    head *LinkedListNode 
} 

// InsertList will insert a item into the list 
func (list *LinkedList) InsertList(data int) { 
    newHead := &LinkedListNode{data, list.head} 
    list.head = newHead 
} 

func main() { 
    var list LinkedList 
    list.InsertList(4) 
    fmt.Printf("node = %+v\n", list.head) 
    list.InsertList(7) 
    fmt.Printf("node = %+v\n", list.head) 
} 
+0

hmmは感覚を作ります。ありがとう –

+0

@HuyLe、Goは、値渡し/参照渡しの区別のナンセンスを含まないため、実際にポインタを他の言語よりシンプルにしています。 Goでは、すべての型の値は常に代入時および関数としてパラメータとして渡されるときに値渡し(コピー)されます。ポインタは単なる値でもあり、他の値のメモリ位置のアドレスを格納するために定義されています。 – kostix

+0

@HuyLeしたがって、ポインタを関数に渡すと、コード内のポインタ値自体を変更するだけでは、その中に格納されているアドレスを書き換えるだけでほとんど意味がなくなり、他の値と同様に、呼び出し元には影響しませんいずれにしても。しかしポインタ値を使って* dereference *(または "chase")することができます - poiner値に格納されているアドレスに保持されている値を保持します。 *その値は任意の方法で変更できます。 – kostix

2

思う:すべての変数は、メモリ内のいくつかの場所に格納されなければならない、とあなたはその場所だけではなく変数自体を保存するために、ポインタを使用することができます。

ポインタを使用してその位置の値を取得または設定するには、「間接指定」演算子を使用する必要があります。たとえば、*nodeは、nodeが指す位置にLinkedListを、*node = newHeadには、nodeが指す位置にLinkedListを設定します。

ポインタを新しいメモリ位置にすることもできますが、その変更は現在のスコープでのみ表示されます。あなたのケースでは、node = &newHeadは、mainnodeポインターではなく、InsertListポインターのnodeポインターにのみ影響します。同じ規則は、メソッドに適用されますけれどもここ

は、通常の機能を使用して単純な例です:

// Changes the value `x` points to 
func modifyValue(x *int) { 
    fmt.Printf(" modifyValue: x=%3d @ %p\n", *x, x) 
    *x = 1 
    fmt.Printf(" modifyValue: x=%3d @ %p\n", *x, x) 
} 

// Changes the pointer `x` itself 
func modifyPointer(x *int) { 
    fmt.Printf("modifyPointer: x=%3d @ %p\n", *x, x) 
    n := 1 
    x = &n 
    fmt.Printf("modifyPointer: x=%3d @ %p\n", *x, x) 
} 

func main() { 
    x := 200 
    fmt.Printf("   main: x=%3d @ %p\n\n", x, &x) 
    modifyPointer(&x) 
    fmt.Printf("   main: x=%3d @ %p\n\n", x, &x) 
    modifyValue(&x) 
    fmt.Printf("   main: x=%3d @ %p\n\n", x, &x) 
} 

出力:

  main: x=200 @ 0x1040e0f8 

modifyPointer: x=200 @ 0x1040e0f8 
modifyPointer: x= 1 @ 0x1040e134 
     main: x=200 @ 0x1040e0f8 

    modifyValue: x=200 @ 0x1040e0f8 
    modifyValue: x= 1 @ 0x1040e0f8 
     main: x= 1 @ 0x1040e0f8 

Playground link

1

ただ

に値参照引数ポイントを変更します
func (node *LinkedList) InsertList(data int) { 
    newHead := LinkedList{data, node} 
    *node = newHead //<- dereference here 
} 
関連する問題