I'm reading the spec about selectors: https://golang.org/ref/spec#Selectors

Why q.M0() is invalid. While p.M0() is valid and q=p. Very strange for me.
The relevant source code:
type T0 struct {
x int
}
func (*T0) M0()
type T1 struct {
y int
}
func (T1) M1()
type T2 struct {
z int
T1
*T0
}
func (*T2) M2()
type Q *T2
var t T2 // with t.T0 != nil
var p *T2 // with p != nil and (*p).T0 != nil
var q Q = p
p.M0() // ((*p).T0).M0() M0 expects *T0 receiver
q.M0() // (*q).M0 is valid but not a field selector
Why
q.M0()is invalid. Whilep.M0()is valid andq=p. Very strange for me.
q is initialized like var q Q = p, but it does not mean they are equal. The assignment is valid because it does not violate the assignability rules, but type of q is different than type of p.
Type of q is Q (where type Q *T2), and type of p is *T2.
In Go, methods belong to a specific type. When you do this:
type Q *T2
It creates a new type named Q (*T2 being its underlying type). The new type will have 0 methods, it does not "inherit" any methods from *T2, hence q.M0() will be a compile-time error:
q.M0 undefined (type Q has no field or method M0)
Note:
You may still think it's strange because M0() is declared like this:
func (*T0) M0()
It has *T0 receiver so it belongs to the type *T0, yet type of p is *T2, so *T2 should not have this M0() method and therefore p.M0() should also be invalid. But T2 is a struct which embeds *T0, and so methods of *T0 are promoted, and they will be in the method set of T2.
Also see this related question: Golang: Why selector to pointers is illegal after comparison?
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With