为了账号安全,请及时绑定邮箱和手机立即绑定

函数中对结构的指针和引用

函数中对结构的指针和引用

Go
慕尼黑的夜晚无繁华 2023-06-05 16:53:41
我从 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"}

您正在用指向的新实例的新指针覆盖局部变量 。它现在指向与调用者指针不同的内存,因此调用者什么也看不到。vUser

如果您改为这样做:

*v = User{Name: "Paul"}

然后,指向相同内存的相同指针将被的新实例覆盖。User

同样,在 中Modify3,您有一个指向指针 的指针。所以你的调用者和函数都有一个局部变量,它指向一个内存位置,这个内存位置包含另一个内存位置,可以在其中找到实际值。请注意,这在 Go 中是一种非常不寻常(但并非闻所未闻)的模式,但在其他语言中很常见。当你这样做时:

*y = &User{Name: "Bob"}

您正在创建一个指向 new 的新指针User,并将该新指针存储在外部指针指向的共享内存中。因此,函数和调用者再次共享内存,并且都将看到更改。


查看完整回答
反对 回复 2023-06-05
  • 1 回答
  • 0 关注
  • 98 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信