例如
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
不都是指向结构本身的指针吗?为什么在我修改函数中的结构时会出现行为差异?
golang 是否在解析参数时在 changeByValueStruct
中创建一个新结构?
最佳答案
当您将指针作为参数传递时,幕后发生的事情是创建该指针的副本并将其传递给底层函数。它不应与按引用传递相混淆。
让我们看一个例子以更好地理解它:
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。如果您熟悉其他语言中可用的按引用传递范例,您可能希望能够完全修改引用的对象,但这并没有发生。这是因为您正在修改作为参数传递的指针的副本。
你可能想知道,如果一切都按值传递,什么时候应该传递指针,什么时候传递值。传递值向调用者函数保证传递的结构不会受到任何更改,因此当您需要此行为时,请寻找值。这样做的缺点是制作了整个对象的副本,如果它太大,内存就会成为一个问题。
如果您将一个大结构作为参数传递,使用指针会更好,因为它可以节省空间,但您无法保证对象不会发生任何变化。
关于pointers - 传递结构和结构指针有什么区别,它们不是都是指针吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44872739/