Struct embedding
Let's say we want to create a workshop based on our Course
struct.
We could create a new struct Workshop
and copy all the fields from Course
into it. But that would be a lot of duplication.
Let's start by creating a new struct Workshop
:
type Workshop struct {
Course Course
Date time.Time
}
We can instantiate and print it:
func main() {
var w = Workshop{
Course: Course{Name: "Go", Instructor: Instructor{FirstName: "Lasse", LastName: "Jensen"}},
Date: time.Now(),
}
fmt.Printf("%v", w)
}
Looks good? Well, it works, but we can do better.
To avoid duplication, we can embed the Course
struct into the Workshop
struct:
type Workshop struct {
Course
Date time.Time
}
We simply remove the identifier Course
and keep the type to embed it.
Is it extending the
Course
struct? No, under the hood it copies the fields fromCourse
intoWorkshop
.
A downside of using embedding is that fields cannot be set directly when creating an instance of the Workshop
struct.
func main() {
var w = Workshop{
Name: "Go", // Error: unknown field 'Name' in struct literal
Instructor: Instructor{FirstName: "Lasse", LastName: "Jensen"}, // Error: unknown field 'Instructor' in struct literal
Date: time.Now(),
}
fmt.Printf("%v", w)
}
To set the fields, we need to use the Course
type:
func main() {
var w = Workshop{
Course: Course{Name: "Go", Instructor: Instructor{FirstName: "Lasse", LastName: "Jensen"}},
Date: time.Now(),
}
fmt.Printf("%v", w)
}
One way to make this look nicer is to use the factory pattern:
func NewWorkshop(courseName string, instructor Instructor, date time.Time) Workshop {
return Workshop{
Course: Course{Name: courseName, Instructor: instructor},
Date: date,
}
}
Order of properties
What happens if we have the same field in both the Workshop
and Course
structs?
type Workshop struct {
Course
Date time.Time
Name string // Error: duplicate field 'Name' ???
}
Will we get an error? No, Go will use the field from the
Workshop
struct as it is the "closest".
We can still set the name of the Course.Name
field, but we need to be explicit:
w.Name = "Go workshop"
w.Course.Name = "Go course"
w.Course.Name
is also called an embedding property.
Sharing of methods
When you embed a struct, you also get access to its methods. Neat!