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.