eadfrith <
eadf...@gmail.com> writes:
> Firstly, where in the spec does it explain that selectors
> automatically reference values? The section on Selectors (http://
>
golang.org/doc/go_spec.html#Selectors) explains that selectors
> automatically dereference pointers, so we can do this:
>
> type S struct {}
> func (s S) m1 {}
> func (s *S) m2 {}
>
> ap := &S{};
> ap.m1(); // equivalent to (*ap).m1()
>
> but I was surprised to find that we can also do this:
>
> av := S{};
> av.m2(); // equivalent to (&ap).m2();
This is specifed in the section on Calls:
A method call x.m() is valid if the method set of (the type of) x
contains m and the argument list is compatible with the parameter
list of m. If x is addressable and &x's method set contains m,
x.m() is shorthand for (&x).m():
We introduced this because it is very common for a struct to provide
pointer methods and to be used with values. After some experience
with writing (&x).m(), it seemed clear that that was both common and
tedious, and so we permitted the compiler to take the address
automatically.
> This strikes me as somewhat unsafe. The author of struct S could
> change m2 from taking a value reciever, which would cause a copy of av
> to be passed, to taking a pointer, which would allow updates to av,
> without any changes to client code.
That is true, but we think that typically it is the definer of the
type which controls whether methods are read-only, not the user.
> My second question is why this automatic referencing is not allowed
> for interfaces? Given the interface definition:
>
> type IM interface {
> m1();
> m2();
> }
>
> we can do this:
>
> var b IM = &av;
>
> but not this
>
> var b IM = av; // not allowed
>
> The reason seems to be that automatic dereferencing is supported for
> interface types but automatic referencing is not. This means that the
> type *S implements IM (b will be automatically dereferenced in calls
> to m1), but S does not, since b will not be automatically referenced
> in calls to m2.
>
> Is this understanding correct?
Yes, that is correct.
It would be possible to implement "var b IM = av" to automatically
take the address of "av" when necessary to make the value fit the
methods, but that seems both more surprising and less common than
permitting a direct method call to take the address of the value being
passed to the method.
Ian