I am currently learning to program with Go language. I am having some difficulties understanding Go pointers (and my C/C++ is far away now...). In the Tour of Go #52 (http:/
There are two different rules of the Go language used by your examples:
It is possible to derive a method with a pointer receiver from a method with a value receiver. Thus func (v Vertex) Abs() float64
will automatically generate an additional method implementation:
func (v Vertex) Abs() float64 { return math.Sqrt(v.X*v.X+v.Y*v.Y) }
func (v *Vertex) Abs() float64 { return Vertex.Abs(*v) } // GENERATED METHOD
The compiler will automatically find the generated method:
v := &Vertex{3, 4}
v.Abs() // calls the generated method
Go can automatically take the address of a variable. In the following example:
func (v *Vertex) Abs() float64 { return math.Sqrt(v.X*v.X+v.Y*v.Y) }
func main() {
v := Vertex{3, 4}
v.Abs()
}
the expression v.Abs()
is equivalent to the following code:
vp := &v
vp.Abs()
The difference is pass-by-referenve vs pass-by-value.
In func f(v Vertex)
the argument is copied into parameter v
. In func f(v *Vertex)
a pointer to an existing Vertex
instance is passed.
When using methods, some of the dereferencing can be done for you, so you can have a method func (v *Vertex) f()
and call it without taking a pointer first: v := Vertex{...}; v.f()
. This is just a grain of syntax sugar, AFAIK.
There are two main differences in those examples:
func (v *Vertex) Abs()....
The receiver will be passed-by-reference for v and you would be able to call this method only on pointers:
v := Vertex{1,3}
v.Abs() // This will result in compile time error
&v.Abs() // But this will work
On the other hand
func (v Vertex) Abs() ....
You can call this method on both pointers and structs. The receiver will be passed-by-value even when you call this method on pointers.
v := Vertex{1,3}
v.Abs() // This will work, v will be copied.
&v.Abs() // This will also work, v will also be copied.
You can declare both func (v *Vertex)
and func (v Vertex)
.
There are differences. For example, the non-pointer receiver form forces the method to work on a copy. This way the method is not able to mutate the instance it was invoked on - it can access only the copy. Which might be ineffective in terms of e.g. time/memory performance/consumption etc.
OTOH, pointer to instances and methods with pointer receivers allow for easy instance sharing (and mutating) where desirable.
More details here.
As the specification says
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 your case v.Abs() is shorthand for &v.Abs() if method is addressable.