Structs can “inherit” from other structs by a method known as embeding. Here is a simple example:
package main
import (
"fmt"
)
type a struct {
Name string
}
//embeds a value of type a
type b struct {
a
}
//embeds a pointer to an a
type c struct {
*a
}
func main() {
a := a{Name: "Janeway"}
fmt.Println(a.Name)
b := &b{a: a}
fmt.Println(b.Name)
c := &c{a: &a}
fmt.Println(c.Name)
}
If the struct that is embeded has methods then the struct into which it is embedded will also have those methods
package main
import (
"fmt"
)
type a struct {
Name string
}
func (as a) NameLength() int {
return len(as.Name)
}
type b struct {
a
}
type c struct {
*a
}
func main() {
a := a{Name: "Janeway"}
fmt.Println(a.Name)
fmt.Println(a.NameLength())
b := &b{a: a}
fmt.Println(b.Name)
fmt.Println(b.NameLength())
c := &c{a: &a}
fmt.Println(c.Name)
fmt.Println(c.NameLength())
}
So what happens if b also has a method called NameLength?
package main
import (
"fmt"
)
type a struct{
Name string
}
func (as a)NameLength() int{
return len(as.Name)
}
type b struct{
a
}
func (bs b)NameLength() int{
return len(bs.Name) -1
}
type c struct{
*a
}
func main() {
a := a{Name:"Janeway"}
fmt.Println(a.Name)
fmt.Println(a.NameLength())
b := &b{a:a}
fmt.Println(b.Name)
fmt.Println(b.NameLength()) //this is the method on b itself
fmt.Println(b.a.NameLength()) //notice we can still reference the behaviour of a
c := &c{a:&a}
fmt.Println(c.Name)
fmt.Println(c.NameLength())
}
//will output
//Janeway
//7
//Janeway
//6
//7
//Janeway
//7
So it acts as I think we would expect it to. If there is a method on the referenced struct that matches it will chose that implementation, however if you want to call the method on the embedded struct you can do so by going up the chain of properties
b.a.MethodName()
So what’s the difference between this and classical inheritance?
- The embedded struct knows nothing about the struct in which it has been embedded. There is no way to go down the chain you cannot do
a.b.MethodName - There is no way to have the concept of
abstractmethods that the embedding struct is forced to implement.
Again the rules around pointers apply. If you modify an embeded pointer you will also modify the value of that pointer for anything else using the same pointer address.