Go uses struct and interfaces to help developers achieve composition. We can embed structs within other structs and access the methods and variables of the child struct from the parent struct.
package main
import "fmt"
type bag struct {
items []string
}
func (b *bag) listItems() {
list := ""
for _, item := range b.items {
list += item + " "
}
fmt.Println("items in bag: ", list)
}
func (b *bag) addItem(itemName string) {
b.items = append(b.items, itemName)
}
type Player struct {
name string
age int
bag
}
func (p *Player) talk() {
fmt.Printf("Hello my name is %s. I am %d years old.\n", p.name, p.age)
}
func main() {
bookBag := bag{items: []string{}}
me := Player{name: "Joash", age: 26, bag: bookBag}
me.talk()
me.bag.addItem("shovel")
me.bag.addItem("pencil")
me.bag.listItems()
me.addItem("eraser")
me.listItems()
}
struct-embedding.go Copy
The name of the struct bag serves as the field we use to access its methods and data (via me.bag). Please note that the declaration for Player is:
type Player struct {
name string
age int
bag
}
And not:
type Player struct {
name string
age int
bag bag
}
The latter prevents us from accessing the methods on bag e.g. listItems and addItem as if they were methods on the Player object.