I've been playing with interfaces and structures in Golang in an attempt to implement "inheritance", but I am confident that I've done it in a wrong way. It would be easier to explain with an example.
I want to create structures of different living things. I want them to have the GetName() method:
type LivingThingProvider interface {
GetName() string
}
Now, all of them should have names and birthdays. For that, I am creating a structure and embedding the interface to it:
type LivingThing struct {
birthday string
name string
LivingThingProvider
}
I want to add a couple of methods which would be the same for all living beings:
func (this *LivingThing) Initialize() {
this.birthday = time.Now().Format("02.01.2006")
}
func (this LivingThing) GetBirthday() string {
return this.birthday
}
Now, here are the structures that are supposed to "implement" LivingThing:
type Frog struct {
insectsEaten int
LivingThing
}
func (this Frog) GetName() string {
return fmt.Sprintf("%s-the-Frog-proud-eater-of-%d-insects", this.name, this.insectsEaten)
}
type RobotMan struct {
LivingThing
}
func (this RobotMan) GetName() string {
h := sha256.New()
h.Write([]byte(this.birthday))
return fmt.Sprintf("%s-%X", this.name, h.Sum(nil))
}
In the main function, I am creating and adding a frog and a robotman to a slice, after that I loop over it:
func main() {
fr := Frog{}
fr.name = "Dizzy"
fr.insectsEaten = 586
fr.LivingThingProvider = fr
rm := RobotMan{}
rm.name = "Bender"
rm.LivingThingProvider = rm
fr.Initialize()
rm.Initialize()
entities := []LivingThing{fr.LivingThing, rm.LivingThing}
for _, ent := range entities {
fmt.Printf("Hi, I am %s!\n", ent.GetName())
fmt.Printf("I was born on the %s.\n", ent.GetBirthday())
}
}
Everything works as expected, but if I remove the GetName() method from the Frog or RobotMan structure, it will compile and panic after run:
panic: runtime error: invalid memory address or nil pointer dereference
Here's the playground link: https://play.golang.org/p/h2VgvdcXJQA
My questions are the following:
1. Is what I've done "dirty" in terms of Go? If so, how to do it in a correct way?
1a. Especially, is it fine to assign the structure itself to its embedded interface field (fr.LivingThingProvider = fr)?
2. Why doesn't Go compiler check if Frog and RobotMan implement the LivingThingProvider interface?
Thank you very much in advance!