package main
import (
"fmt"
)
type T interface{
ToChild() T
Test()
Test2()
}
type A struct {
}
func (a *A)Test(){
fmt.Println("A-Test")
}
func (a *A)Test2(){
a.ToChild().Test()
}
type B struct {
A
}
func (b *B)Test(){
fmt.Println("B-Test")
}
func (b *B)ToChild()T{
return b
}
func main(){
var a T
a = &B{}
a.Test2()
}
When I run your code in the Go playground, I get a compile-time error message:
main.go:20: a.ToChild undefined (type *A has no field or method ToChild)
This makes sense, as A has indeed no ToChild method.
I wonder how you manage to execute the code despite this compile-time error. What is your go version? Are you using cgo rather than go?
(Side node: The terms “base struct” and “ToChild” indicate that you think in terms of object orientation and inheritance. Struct embedding is different from inheritance, and using OO terms can cause confusion about what actually happens when embedding a struct versus what you expect to happen in an OO language.)
Type A “implements” interface T by delegating all of T’s methods to the embedded anonymous field of type T. This is why the compiler does not complain.
At runtime, the embedded T field is nil. Test this with Printf:
func main() {
var a T
a = &B{}
fmt.Printf("%+v\n", a)
a.Test2()
}
which prints
&{A:{T:<nil>}}
And this the reason for the nil pointer panic.
To avoid this, instantiate the embedded A field with something that implements T.
func main() {
b := &B{} // b has Test() and ToChild()
fmt.Printf("%+v\n", b)
a := A{b} // a has Test2() and both methods of b
fmt.Printf("%+v\n", a)
ba := &B{a} // b has all methods of a
fmt.Printf("%+v\n", ba)
ba.Test2()
}