通过将指针传递给Go中的函数来获取不同的值

Say I want to pass a pointer to a function and change the value of a struct which that pointer points to by doing so. I would normally do this by dereferencing the pointer:

type Test struct { Value int}
func main() {
   var i Test = Test {2}
   var p *Test = &i
   f(p)
   println(i.Value)  // 4
}
func f(p *Test) {
   *p = Test{4}
}

My question is, why this code doesn't change the value

type Test struct { Value int}
func main() {
   var i Test = Test {2}
   var p *Test = &i
   f(p)
   println(i.Value)  // 2
}
func f(p *Test) {
   // ?
   p = &Test{4}
}

while this one does:

type Test struct { Value int}
func main() {
   var i Test = Test {2}
   var p *Test = &i
   f(p)
   println(i.Value)  // 4
}
func f(p *Test) {
   p.Value = 4
}

Because this line:

p = &Test{4}

Just assigns a new pointer value to the p variable. Inside the f() function, p is just a local variable. By assigning any new value to p, you are just changing the value of the local variable and not the pointed value.

The p local variable in f() has nothing to do with the p local variable in main(). If you change p in f(), it will not change p in main() (and it won't change the pointed struct value either).

In your second example:

p.Value = 4

It is a shorthand for:

(*p).Value = 4

This changes the pointed value, hence you will observe the change when f() returns.

Note:

Just as a side note, if in your main() function you would pass the address of p (the local variable in main() which is a pointer) to function f(), you could modify the address stored in main's p:

func f(p **Test) {
    *p = &Test{4}
}

And from main(), call it like:

var i Test = Test{2}
var p *Test = &i
f(&p)
println(i.Value) // 2 - Note that 'i' won't change!
println(p.Value) // 4 - Only the address in 'p' to the new struct value created in f()

But obviously passing a single pointer *Test and modifying the pointed value (p.Value = 4) is more efficient, much more convenient and much cleaner.