Why does the pointer receiver method still work when it gets the value?

I just played with Exercise 51 on the Tour of Go . The explanation states that the Scale method does not work when it gets Vertex instead of a pointer to Vertex .

However, when I change the declaration v := &Vertex{3, 4} to v := Vertex{3, 4} in main , the only change in the output is the absence of & to mark the pointer.

So why does Scale modify the resulting variable, even if the variable is not a pointer?

+4
source share
2 answers

He does not โ€œreceiveโ€ meaning. Go is strongly typed, so if a pointer to T is prescribed, a pointer to T ( *T ) is the only option that could be the value for such a typed place.

The "magic" is in the compiler, which effectively overwrites your code under certain conditions:

The method xm() call is valid if the set of methods (type) x contains m , and the argument list can be assigned to the parameter list m . If x is addressed, and the set of methods & x contains m , xm() is short for (&x).m() :

Related: Method Sets

+8
source

The difference the tour offers does not actually change v := &Vertex{3, 4} to v:= Vertex{3, 4} , but rather changes the definitions of these two methods so that they work on values โ€‹โ€‹instead of pointers. So, for example, for Scale , func (v *Vertex) Scale(f float64) {... becomes func (v Vertex) Scale(f float64) {... (note that (v *Vertex) , the pointer value becomes (v Vertex) , a value without a pointer). In both cases, you must leave the v declaration as v := &Vertex{3, 4} .

You will notice that in the first case, when the methods take pointers, the output is &{15 20} 25 . However, when methods take values, not pointers, the output is &{3 4} 5 .

In both cases, v is a pointer to a Vertex object. In the first case, the pointer is passed to the methods, and everything works as expected - any changes made to the Vertex object are made with the original value, so these changes are saved after the method returns. In the second case, although v is still a pointer, the Go compiler is smart enough to convert v.Scale(5) to (*v).Scale(5) , where v dereferenced and the resulting value is passed to Scale .

+1
source

Source: https://habr.com/ru/post/1494759/


All Articles