例如
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 *Vertex和myStruct Vertex一个指针指向结构本身?当我在函数中修改结构时,为什么行为上会有差异?
myStructRef *Vertex
myStruct Vertex
golang在changeByValueStruct解析参数时是否在创建新的结构?
changeByValueStruct
在Go中只有一种传递参数的方法,那就是 按值 。这意味着总是在传递参数时,会创建值的副本并将其传递给函数。
当您将指针作为参数传递时,实际上是创建了该指针的副本并将其传递给基础函数。不应将其与传递引用混淆。
让我们看一个例子来更好地理解它:
package main 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) p = Point{0, 0} modifyReference(&p) fmt.Println(p) // prints (0, 0) }
ModifyValue 函数内部发生的事情是修改了Point结构的完全不同的实例,因此调用函数时传递的值不受影响。
在第二个示例中,传递了指向该结构的指针,以便可以以从外部可见的方式修改该结构的字段。
最有趣的一点是最后一个函数 ModifyReference 。如果您熟悉其他语言提供的“按引用传递”范例,则可以完全修改被引用的对象,但这不会发生。这是因为您正在修改作为参数传递的指针的 副本 。
您可能想知道,如果一切都是按值传递的,则何时应传递指针以及何时传递值。传递值可确保调用方函数传递的结构不会受到任何更改,因此,在需要此行为时,请选择该值。不利的一面是制作了整个对象的副本,如果副本太大,则需要考虑内存问题。
如果要传递大结构作为参数,则使用指针会更好,因为它可以节省空间,但是您无法保证对象不会受到任何更改。