It's because when you pass arguments to functions etc, they are always passed by value.
In other words, even though you are accepting a pointer in the function parameter, the address of the struct will be copied.
Then when you assign to s
to try and change the address it only changes that local copy, not the one outside the function.
To change the address from within the function you would need to pass in a pointer pointer, then assign to the dereferenced s
, for example:
package main
import (
"fmt"
)
type Pod struct {
Power int
}
func main() {
pod := &Pod{1}
fmt.Println(pod.Power)
Change(&pod)
fmt.Println(pod.Power)
}
func Change(s **Pod) {
*s = &Pod{2}
}
In this case a copy of an address is still being passed into the function, but because it's a pointer to a pointer it means that when you dereference s
as *s
you will get the address of the struct outside of the function. This means if you assign to *s
you can change the address of the pointer outside the function.
Of course, like Andy Schweig says, you probably wouldn't really want to do that though, and would probably just change individual fields as needed with the normal pointer version of the function.
package main
import (
"fmt"
)
type Pod struct {
Power int
}
func main() {
pod := &Pod{1}
fmt.Println(pod.Power)
Change(pod)
fmt.Println(pod.Power)
}
func Change(s *Pod) {
s.Power = 2
}
This works because when you type s.Power = 2
Go will actually do something like (*s).Power = 2
for you. So it automatically dereferences s
for you which gives you the actual Pod
struct to work with.
You can't do *s = &Pod{2}
in this normal pointer example because in that case *s
will actually equal type Pod
, not *Pod
.
Because of that if you want to use the &Pod{2}
syntax to assign an address you need to pass a pointer to the pointer. In the case of s **Pod
the dereferenced *s
will point to the address of the Pod
instead of the actual Pod
, so *s
will be of type *Pod
which allows you to assign &Pod{2}
.
Having said all of that, a **Pod
is only required if you want to assign an address with the &Pod{2}
syntax.
If you don't need to use the &Pod{2}
syntax you can just dereference s
and assign with a normal Pod{2}
.
package main
import (
"fmt"
)
type Pod struct {
Power int
}
func main() {
pod := &Pod{1}
fmt.Println(pod.Power)
Change(pod)
fmt.Println(pod.Power)
}
func Change(s *Pod) {
*s = Pod{2}
}
This also works, because now s
is a copy of an address, and when you dereference you get to the value outside the function which is type Pod
, not *Pod
.
That means you can just assign to it by removing the &
.
Basically if you use &
it means you want to assign an address rather than the actual value.
I hope this explanation isn't too confusing. I explained using a **Pod
because I thought you wanted to use the &Pod{2}
syntax rather than Pod{2}
, but if that's not the case then my s.Power = 2
or *s = Pod{2}
examples may make more sense.