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
}
Go programming language allows you to pass a pointer to a function. To do so, simply declare the function parameter as a pointer type.
Pass-by-pointer means to pass a pointer argument in the calling function to the corresponding formal parameter of the called function. The called function can modify the value of the variable to which the pointer argument points. When you use pass-by-pointer, a copy of the pointer is passed to the function.
To find out the value (data) a pointer it points to, we need to use * operator, also called dereferencing operator which if placed before a pointer variable (like & operator to get memory address), it returns the data in that memory.
While Java passes objects by reference always, Go passes by value always (i.e. it creates a copy of the value in the function); if you pass something to a function, and that function modifies that value, the caller won't see those changes.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With