The title might be a little confusing because I’m not sure how to explain in one sentence (one question) without an example and a more detailed story.
To clearly explain what the question in the title means, let me start from a situation that behaves as I expect.
package main
import (
"fmt"
"reflect"
)
type MyType1 struct {
MyType2
}
type MyType2 struct {
}
func (MyType2) Function1() {
}
func (*MyType2) Function2() {
}
func main() {
t1 := reflect.TypeOf(MyType1{})
t2 := reflect.TypeOf(&MyType1{})
fmt.Println(t1, "has", t1.NumMethod(), "methods:")
for i := 0; i < t1.NumMethod(); i++ {
fmt.Print(" method#", i, ": ", t1.Method(i).Name, "\n")
}
fmt.Println(t2, "has", t2.NumMethod(), "methods:")
for i := 0; i < t2.NumMethod(); i++ {
fmt.Print(" method#", i, ": ", t2.Method(i).Name, "\n")
}
}
When the type embedding is based on “type” (not correct name, but let’s call it like that) everything behaves as I expect. The structure MyType1
has a MyType2
embedded field (“type” embedded field) so the type MyType1
will have the method (MyType1)Function1()
in its method set and the type *MyType1
will have the methods (*MyType1)Function1()
and (*MyType1)Function2()
in its method set. So, each type (MyType1
and *MyType1
) will get their corresponding methods. *MyType1
will get the method (*MyType1)Function1()
because it’s implicitly arises from (MyType1)Function1()
. So, as I said before, everything is expected. To prove this, I also used the standard “reflect” package and got the following printout:
main.MyType1 has 1 methods:
method#0: Function1
*main.MyType1 has 2 methods:
method#0: Function1
method#1: Function2
A strange behavior occurs when I replace the “type” embedded field with a “pointer type” embedded field (MyType1
now has *MyType2
instead of MyType2
). So the code looks like this:
package main
import (
"fmt"
"reflect"
)
type MyType1 struct {
*MyType2
}
type MyType2 struct {
}
func (MyType2) Function1() {
}
func (*MyType2) Function2() {
}
func main() {
t1 := reflect.TypeOf(MyType1{})
t2 := reflect.TypeOf(&MyType1{})
fmt.Println(t1, "has", t1.NumMethod(), "methods:")
for i := 0; i < t1.NumMethod(); i++ {
fmt.Print(" method#", i, ": ", t1.Method(i).Name, "\n")
}
fmt.Println(t2, "has", t2.NumMethod(), "methods:")
for i := 0; i < t2.NumMethod(); i++ {
fmt.Print(" method#", i, ": ", t2.Method(i).Name, "\n")
}
}
Now what is actually the crux of the problem. The prints is:
main.MyType1 has 2 methods:
method#0: Function1
method#1: Function2
*main.MyType1 has 2 methods:
method#0: Function1
method#1: Function2
So, somehow MyType1
also has method (MyType1)Function2()
even though it is not declared as value receiver method for type MyType2
.
Does anyone have any logical explanation as to why this is happening?