2017-07-02 139 views
-1

例如傳遞一個結構體和結構體的指針有什麼區別,他們不是兩個指針嗎?

var myStructRef *Vertex 
var myStruct Vertex 
myStructRef = &Vertex{2, 3} 
myStruct = Vertex{2, 3} 

fmt.Println(myStructRef) 
fmt.Println(myStruct) 
changeByReferenceStruct(myStructRef) 
changeByValueStruct(myStruct) 
fmt.Println(myStructRef) 
fmt.Println(myStruct) 

而且

func changeByValueStruct(myStruct Vertex) { 
    myStruct.X = 5 
    fmt.Println(myStruct) 
} 


func changeByReferenceStruct(myStruct *Vertex) { 
    myStruct.X = 7 
    fmt.Println(myStruct) 
} 

是不是都myStructRef *VertexmyStruct Vertex指向結構本身的指針?爲什麼在修改函數中的結構時,行爲會有差異?

golang是否在changeByValueStruct中創建了一個新的結構,它解析參數?

+0

結構值是一個結構值,而不是指向結構值的指針;指向結構值的指針是指針,而不是指向指針的指針。 Go文檔中的內容給出了普通結構值是指針的印象? – Adrian

回答

4

有在圍棋傳遞參數只有一個辦法,那就是通過價值。這意味着總是在傳遞參數時創建一個值的副本並將其傳遞給函數。

當您將指針作爲參數傳遞時,引擎蓋下會發生什麼,該指針的副本被創建並傳遞給底層函數。它不應該與通過引用混淆。

讓我們看一個例子,以更好地把握它: 包主要

import (
    "fmt" 
) 

type Point struct { 
    x int 
    y int 
} 

func (p Point) String() string { 
    return fmt.Sprintf("(%d, %d)", p.x, p.y) 
} 

func modifyValue(point Point) { 
    point.x += 10 
} 

func modifyPointer(point *Point) { 
    point.x = 5 
    point.y = 5 
} 

func modifyReference(point *Point) { 
    point = &Point{5, 5} 
} 

func main() { 
    p := Point{0, 0} 
    fmt.Println(p) // prints (0, 0) 

    modifyValue(p) 
    fmt.Println(p) // prints (0, 0) 

    modifyPointer(&p) 
    fmt.Println(p) // prints (5, 5) 

    modifyReference(&p) 
    fmt.Println(p) // prints (0, 0) 
} 

會發生什麼內部modifyValue功能是Point結構的一個完全不同的情況下被修改,所以調用時傳遞的值功能不受影響。

在第二個示例中,傳遞了指向該結構的指針,以便可以從外部可見的方式修改該結構的字段。

最有趣的一點是最後一個功能modifyReference。如果您熟悉其他語言中的傳遞引用範例,則您會期望能夠完全修改引用的對象。無論如何,這不會發生。這是因爲您正在修改作爲參數傳遞的指針的副本

如果所有的東西都是按值傳遞的,你應該什麼時候傳遞指針和值。傳遞值可確保調用者函數傳遞的結構不會遭受任何更改,因此,在需要時,請查找值。這樣做的缺點是整個對象的拷貝被製作,如果它太大,內存就成了一個問題。

如果傳遞一個大結構作爲參數,使用指針會更好,因爲它節省了空間,但是失去了保證對象不會發生任何更改的保證。

3

將結構體傳遞給函數參數使值的副本。並且結構體的指針不傳遞。所以傳遞struct不能更新字段值。

package main 

import (
    "fmt" 
) 

type Foo struct { 
    value int 
} 

func PassStruct(foo Foo) { 
    foo.value = 1 
} 

func PassStructPointer(foo *Foo) { 
    foo.value = 1 
} 

func main() { 
    var foo Foo 

    fmt.Printf("before PassStruct: %v\n", foo.value) 
    PassStruct(foo) 
    fmt.Printf("after PassStruct: %v\n", foo.value) 

    fmt.Printf("before PassStructPointer: %v\n", foo.value) 
    PassStructPointer(&foo) 
    fmt.Printf("after PassStructPointer: %v\n", foo.value) 
} 

https://play.golang.org/p/AM__JwyaJa

+0

但在內部,一個包含struct的變量只是一個指向結構體的指針嗎? – user3591466

+0

正如我在上面所說的,傳遞結構體制作值的拷貝。 – mattn

+0

因此,它創建一個具有不同地址的相同值的新結構? – user3591466