Go Composition
Go, unlike other object-oriented languages like Java or C++, doesn’t have classes. Instead, it uses structs and interfaces to achieve similar functionalities, leveraging a powerful concept called composition. Composition in Go focuses on building complex types by combining simpler ones, promoting code reusability and flexibility. This differs from inheritance, where types inherit properties and methods from a parent class.
Let’s illustrate with an example. Imagine building a system to represent different types of content, such as blogs and news articles. We can define individual structs for each:
type Author struct {
Name string
Email string
}
type BlogPost struct {
Title string
Content string
Author Author
Comments []string
}
type NewsArticle struct {
Headline string
Body string
Author Author
Source string
}
Notice how both BlogPost
and NewsArticle
include an Author
struct. This is composition in action. Rather than creating a base class and inheriting from it, we embed the Author
struct directly, allowing BlogPost
and NewsArticle
to have an author without explicit inheritance.
We can extend this idea further. Consider adding publishing information:
type PublicationInfo struct {
PublishedDate string
Publisher string
}
type BlogPost struct {
Title string
Content string
Author Author
Comments []string
PublicationInfo PublicationInfo
}
type NewsArticle struct {
Headline string
Body string
Author Author
Source string
PublicationInfo PublicationInfo
}
Now, both types incorporate Author
and PublicationInfo
. This illustrates the flexibility of composition. You combine the functionalities you need without the rigidity and potential issues of deep inheritance hierarchies.
Accessing embedded fields is straightforward:
func main() {
blog := BlogPost{
Title: "Go Composition",
Content: "Explaining composition...",
Author: Author{
Name: "John Doe",
Email: "john.doe@example.com",
},
PublicationInfo: PublicationInfo{
PublishedDate: "2024-05-05",
Publisher: "Example Blog Site",
},
}
fmt.Println("Author Name:", blog.Author.Name) // Accessing embedded Author
fmt.Println("Published Date:", blog.PublicationInfo.PublishedDate) // Accessing embedded PublicationInfo
}
Go’s composition approach encourages creating small, focused types that can be combined in various ways. This modularity leads to more maintainable, understandable, and reusable code.