Home >Backend Development >Golang >Why Does a Go Method with a Pointer Receiver Modify a Non-Pointer Argument?
In Go, methods with pointer receivers are known to preserve the original values of variables they operate on. However, there seems to be an apparent contradiction when a method expects a pointer argument and is passed a non-pointer value.
Consider the below snippet for Exercise 51 in the Tour of Go:
func (v *Vertex) Scale(f float64) { v.X *= f v.Y *= f } func main() { v := &Vertex{3, 4} v.Scale(2) fmt.Println(v) // Output: &{6 8} }
According to the explanation, the Scale method should not modify v since it receives a pointer to a Vertex (*Vertex) instead of a Vertex itself.
However, when we change the v := &Vertex{3, 4} line to v := Vertex{3, 4} in main, the output changes from &{6 8} to {6 8} (notice the missing &). This indicates that v has been modified, even though it was passed as a non-pointer value.
The key lies in Go's strongly typed nature and compiler optimizations. Even though the Scale method expects a pointer receiver, it can still accept non-pointer values because Go implicitly converts them to pointers.
Specifically, the compiler rewrites the following code:
v := Vertex{3, 4} v.Scale(2)
to:
(&v).Scale(2)
This means the method is actually called with a pointer to v, which allows it to modify the original value.
The following Go-specific rule explains this behavior:
A method call x.m() is valid if the method set of (the type of) x contains m and the argument list can be assigned to the parameter list of m. If x is addressable and &x's method set contains m, x.m() is shorthand for (&x).m().
In summary, methods with pointer receivers can still modify non-pointer variables because the compiler automatically converts them to pointers to preserve method type safety.
The above is the detailed content of Why Does a Go Method with a Pointer Receiver Modify a Non-Pointer Argument?. For more information, please follow other related articles on the PHP Chinese website!