dpzp5127 2019-01-31 14:55
浏览 57
已采纳

函数中结构的指针和引用

I'm starting with Go and I'm having difficulty understanding pointers and references to structs inside functions.

Considering the example 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)
}

Results:

1st:  0x40e128
1st:  Anne
func:  0x40e140
func:  Duncan
1st:  Anne

2nd:  0x40e158
2nd:  Anne
func:  0x40e158
func:  Paul
2nd:  Anne

3rd:  0x40e188
3rd:  Anne
func:  0x40e198
func:  0x40e188
func:  Bob
3rd:  Bob

4th:  0x40e1b8
4th:  Anne
func:  0x40e1b8
func:  John
4th:  John

Apart from the 1st example, where Ihave no questions, all the others seem to point to the original struct assignment, but 2nd doesn't change the caller value.

Why does this happen, and why is this different than in 3rd and 4th?

  • 写回答

1条回答 默认 最新

  • donglu9898 2019-01-31 15:48
    关注

    The key thing to remember is that everything is passed by value (a.k.a. passed by copying). When you pass a pointer to a function, that parameter is still a local variable in that function, containing a copy of the pointer. That local copy points to the same memory referenced by the caller.

    When you do this:

    v = &User{Name: "Paul"}
    

    You're overwriting your local variable v with a new pointer to a new instance of User. It now points to different memory than the caller's pointer, so the caller sees nothing.

    If you instead did this:

    *v = User{Name: "Paul"}
    

    Then the same pointer, pointing to the same memory, would be overwritten with a new instance of User.

    Likewise, in Modify3, you have a pointer to a pointer. So your caller and function each have a local variable, which points to a memory location, which holds another memory location, where an actual value can be found. Note that this is a very unusual (but not unheard of) pattern in Go, but common in other languages. When you do this:

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

    You're creating a new pointer to a new User, and storing that new pointer in the shared memory pointed to by the outer pointer. So, again, both function and caller are sharing memory and both will see the changes.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥30 这是哪个作者做的宝宝起名网站
  • ¥60 版本过低apk如何修改可以兼容新的安卓系统
  • ¥25 由IPR导致的DRIVER_POWER_STATE_FAILURE蓝屏
  • ¥50 有数据,怎么建立模型求影响全要素生产率的因素
  • ¥50 有数据,怎么用matlab求全要素生产率
  • ¥15 TI的insta-spin例程
  • ¥15 完成下列问题完成下列问题
  • ¥15 C#算法问题, 不知道怎么处理这个数据的转换
  • ¥15 YoloV5 第三方库的版本对照问题
  • ¥15 请完成下列相关问题!