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.