Golang Embedded Structs
Golang doesn’t have the concepts of objects and inheritance. The design of the language is strongly opinionated and follows object-oriented principles (OOP)very closely, hence it favors composition over inheritance. Golang uses structs and methods to emulate objects. For example,
type Bird struct {
}func (b Bird) makeSound() {
fmt.Println("chirp")
}
Golang allows you to compose structs inside of other structs. There are two ways of composing structs: anonymous embedded fields and explicit fields.
Anonymous Embedded Fields
An anonymous embedded field is a struct field that doesn’t have an explicit field name. Structs that have an anonymous field obtain all of the methods and properties of the nested struct. These methods and properties are called “promoted” methods and properties. Anonymous embedded fields can also be accessed by the type name directly.
type Eagle struct {
Bird // anonymous embedded field
}e := Eagle{name: "Baldie"}
e.makeSound() // chirp
e.Bird.makeSound() // chirp
The nuance comes from when structs declare methods and properties that also exist on the embedded struct. In this case, the methods and properties from the embedded struct are “shadowed” and the methods and properties on the struct you are calling will be used. You can still access the shadowed methods and properties by specifically accessing the embedded field and then calling the method or property.
func (e Eagle) makeSound(){
fmt.Println("caw")
}e.makeSound() // caw
e.Bird.makeSound() // chirp
Explicit Fields
You can also explicitly name a field to avoid confusion with promoted and shadowed fields.
type Eagle struct {
b Bird // explicit field
}func (e Eagle) makeSound(){
fmt.Println("caw")
}e := Eagle{name: "Baldie"}e.makeSound() // caw
e.b.makeSound() // chirpe.Bird.makeSound() // error
Here, in order to call Bird
’s makeSound()
method, one has to explicitly access the nested Bird
object using .b
. It is no longer possible to access the underlying .Bird
field.
Conclusion
In summary, there are two ways of composing structs in Golang: anonymous embedded fields and explicit fields.
Anonymous embedded fields allow methods and properties from the embedded struct to automatically get promoted to the nesting struct, but there’s a possibility of those methods and properties getting shadowed if the nesting struct declares methods of properties of the same name.
Explicit fields directly associate a field name with the nested struct, so that accessing the nested struct’s methods and properties are unambiguous. In production code, it’s often better to use explicit fields over anonymous embedded fields to make the code more readable and not surprise yourself with shadowed fields.