Go supports a somewhat unique feature called "struct embedding" or just "embedding", a type of first-class composition (vs what most OOP languages offer, first-class inheritance).
Embedding allows you to embed one struct within another, such that the members of the embedded struct can be referenced as though they were declared on the parent structure:
type Player struct {
Age uint8 `json:"age"`
Name string `json:"name"`
UUID string `json:"uuid"`
}
type PlayerDynamo struct {
Player // PlayerDynamo "embeds" Player
Salary float32 `json:"salary"`
}
An instance of a PlayerDynamo now has both a Player member...
p := PlayerDynamo{}
p.Player.Name
and the embedded fields of Player:
p := PlayerDynamo{}
p.Name // Equivalent to p.Player.Name
Even methods of Player can be invoked on a PlayerDynamo:
func (p Player) String() string {
return fmt.Sprintf("Player %q", p.Name)
}
p := PlayerDynamo{
Player: Player {
Name: "Bob",
},
}
fmt.Println(p.String()) // Player "Bob"
This isn't exactly the same as copying the Age/Name/UUID fields into the PlayerDynamo: When you declare a new PlayerDynamo, you still need to initialize the embedded Player explicitly:
p := PlayerDynamo {
Player: Player {
Name: "test",
Age: 45,
}
Salary: 42
}
Critically, the struct tags are copied over and marshalling to JSON works as expected, with all of the Player fields appearing within the marshalled representation of a PlayerDynamo.
See https://play.golang.org/p/6HMrlVZzIsn for a live example.