猿问

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

我从 Go 开始,我很难理解函数内部结构的指针和引用。

考虑示例https://play.golang.org/p/zd8La4ecNXw

package main


import "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)

}

除了第一个示例,我没有问题,所有其他示例似乎都指向原始结构分配,但第二个不更改调用者值。

为什么会发生这种情况,为什么这与3rd4th不同?


慕尼黑的夜晚无繁华
浏览 99回答 1
1回答

哆啦的时光机

要记住的关键是一切都是按值传递的(也就是通过复制传递)。当您将指针传递给函数时,该参数仍然是该函数中的局部变量,包含指针的副本。该本地副本指向调用者引用的同一内存。当你这样做时:v = &User{Name: "Paul"}您正在用指向的新实例的新指针覆盖局部变量 。它现在指向与调用者指针不同的内存,因此调用者什么也看不到。vUser如果您改为这样做:*v = User{Name: "Paul"}然后,指向相同内存的相同指针将被的新实例覆盖。User同样,在 中Modify3,您有一个指向指针 的指针。所以你的调用者和函数都有一个局部变量,它指向一个内存位置,这个内存位置包含另一个内存位置,可以在其中找到实际值。请注意,这在 Go 中是一种非常不寻常(但并非闻所未闻)的模式,但在其他语言中很常见。当你这样做时:*y = &User{Name: "Bob"}您正在创建一个指向 new 的新指针User,并将该新指针存储在外部指针指向的共享内存中。因此,函数和调用者再次共享内存,并且都将看到更改。
随时随地看视频慕课网APP

相关分类

Go
我要回答