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.

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

报告相同问题?

悬赏问题

  • ¥15 2024-五一综合模拟赛
  • ¥15 下图接收小电路,谁知道原理
  • ¥15 装 pytorch 的时候出了好多问题,遇到这种情况怎么处理?
  • ¥20 IOS游览器某宝手机网页版自动立即购买JavaScript脚本
  • ¥15 手机接入宽带网线,如何释放宽带全部速度
  • ¥30 关于#r语言#的问题:如何对R语言中mfgarch包中构建的garch-midas模型进行样本内长期波动率预测和样本外长期波动率预测
  • ¥15 ETLCloud 处理json多层级问题
  • ¥15 matlab中使用gurobi时报错
  • ¥15 这个主板怎么能扩出一两个sata口
  • ¥15 不是,这到底错哪儿了😭