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