我从 Go 开始,我很难理解函数内部结构的指针和引用。考虑示例https://play.golang.org/p/zd8La4ecNXwpackage mainimport "fmt"type User struct { Name string}func main() { // 1st u := User{Name: "Anne"} fmt.Println("1st: ", &u.Name) fmt.Println("1st: ", u.Name) Modify1(u) fmt.Println("1st: ", u.Name) // 2nd fmt.Println() v := &User{Name: "Anne"} fmt.Println("2nd: ", &v.Name) fmt.Println("2nd: ", v.Name) Modify2(v) fmt.Println("2nd: ", v.Name) // 3rd fmt.Println() y := &User{Name: "Anne"} fmt.Println("3rd: ", &y.Name) fmt.Println("3rd: ", y.Name) Modify3(&y) fmt.Println("3rd: ", y.Name) // 4th fmt.Println() z := &User{Name: "Anne"} fmt.Println("4th: ", &z.Name) fmt.Println("4th: ", z.Name) Modify4(z) fmt.Println("4th: ", z.Name)}func Modify1(u User) { fmt.Println("func: ", &u.Name) u.Name = "Duncan" fmt.Println("func: ", u.Name)}func Modify2(v *User) { fmt.Println("func: ", &v.Name) v = &User{Name: "Paul"} fmt.Println("func: ", v.Name)}func Modify3(y **User) { fmt.Println("func: ", &y) fmt.Println("func: ", &(*y).Name) *y = &User{Name: "Bob"} fmt.Println("func: ", (*y).Name)}func Modify4(z *User) { fmt.Println("func: ", &z.Name) z.Name = "John" fmt.Println("func: ", z.Name)}除了第一个示例,我没有问题,所有其他示例似乎都指向原始结构分配,但第二个不更改调用者值。为什么会发生这种情况,为什么这与3rd和4th不同?
1 回答
哆啦的时光机
TA贡献1779条经验 获得超6个赞
要记住的关键是一切都是按值传递的(也就是通过复制传递)。当您将指针传递给函数时,该参数仍然是该函数中的局部变量,包含指针的副本。该本地副本指向调用者引用的同一内存。
当你这样做时:
v = &User{Name: "Paul"}
您正在用指向的新实例的新指针覆盖局部变量 。它现在指向与调用者指针不同的内存,因此调用者什么也看不到。v
User
如果您改为这样做:
*v = User{Name: "Paul"}
然后,指向相同内存的相同指针将被的新实例覆盖。User
同样,在 中Modify3
,您有一个指向指针 的指针。所以你的调用者和函数都有一个局部变量,它指向一个内存位置,这个内存位置包含另一个内存位置,可以在其中找到实际值。请注意,这在 Go 中是一种非常不寻常(但并非闻所未闻)的模式,但在其他语言中很常见。当你这样做时:
*y = &User{Name: "Bob"}
您正在创建一个指向 new 的新指针User
,并将该新指针存储在外部指针指向的共享内存中。因此,函数和调用者再次共享内存,并且都将看到更改。
- 1 回答
- 0 关注
- 98 浏览
添加回答
举报
0/150
提交
取消