On Thu, Aug 31, 2017 at 11:50 AM,  <macrae.lin...@gmail.com> wrote:
>
> I was bitten this week by not understanding how interfaces in method
> parameters interacted with pointers. After playing around I finally figured
> out these rules
>
> 1. method/function parameters are not coerced by the compiler. If a
> parameter calls for a pointer, it must be a pointer at the call site.
> 2. method receivers *are* coerced by the compiler. Regardless of the
> pointerness/valueness (what is the right adjective here?) of a receiver, the
> compiler will turn the call into the correct one for the method.
> 3. If *any* of the methods you implement an interface with have a pointer
> receiver, then only a pointer of that type will satisfy the interface.
> 4. If *none* of the methods you implement an interface with have a pointer
> receiver, then either a pointer or a value of that type will satisfy the
> interface.
>
> Please tell me if I have any of that wrong but I've got a gist to show for
> it so I think it's right.

Your point 2 is not precisely accurate.  In the specific case of
x.M(), if M takes a pointer receiver, then the compiler will modify
the expression to (&x).M().  This appears in the language spec at
https://golang.org/ref/spec#Calls ("If x is addressable and &x's
method set contains m, x.m() is shorthand for (&x).m()").


> The most surprising result of this is that for a type that implements an
> interface with exclusively value receivers, you can pass either a pointer or
> a value of that type as a function parameter for the interface. Since all
> the methods have value receivers, then it's as if you passed a value to the
> method, but without doing some casting I'm not sure if it is actually passed
> into the method as a value or a pointer.

https://golang.org/ref/spec#Method_sets


> I'd love to understand some of the reasoning behind these seemingly
> conflicting rules. I'm a little puzzled as to why receivers are treated
> differently from parameters, and much more interested in why implementing a
> pointer receiver method forces an interface implementation to be a pointer.

I'm sure I'm too close to the language, but I don't see any conflict
in these rules.

Receivers are treated differently because we found that it was too
annoying to force everyone to write (&x).M() all the time.

The method set of the pointer type is always a superset of the method
set of the value type, because it's trivial to dereference the pointer
to get a value.  It is not always possible to take the address of a
value--some values have no address, such as a value returned by a
function call.

Ian

-- 
You received this message because you are subscribed to the Google Groups 
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to golang-nuts+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to