Embedding & Composition in Go
Go does not support traditional class-based inheritance like Java or C++. Instead, Go uses a powerful concept called composition, and a special form of composition known as embedding.
This design keeps Go programs simple, flexible, and easier to maintain in large production systems.
What Is Composition?
Composition means building complex types by combining simpler types. Instead of inheriting behavior, Go encourages you to reuse functionality by including structs inside other structs.
This follows the principle:
“Favor composition over inheritance.”
Basic Composition Example
Let’s start with a simple example using real-world data.
type Address struct {
City string
State string
Country string
}
Now compose this inside another struct.
type Employee struct {
Name string
ID int
Address Address
}
Here, Employee has an Address.
This is composition.
Using Composed Structs
Let’s create and use an employee record.
func main() {
emp := Employee{
Name: "Arjun",
ID: 101,
Address: Address{
City: "Bangalore",
State: "Karnataka",
Country: "India",
},
}
fmt.Println(emp.Name)
fmt.Println(emp.Address.City)
}
You access nested fields explicitly using the struct name.
What Is Embedding?
Embedding is a special form of composition where a struct is included without a field name.
This allows the embedded struct’s fields and methods to be accessed directly from the outer struct.
Embedding Example
Let’s embed the Address struct.
type Employee struct {
Name string
ID int
Address
}
Now Address is embedded.
Accessing Embedded Fields
Create an employee and access fields directly.
func main() {
emp := Employee{
Name: "Neha",
ID: 102,
Address: Address{
City: "Hyderabad",
State: "Telangana",
Country: "India",
},
}
fmt.Println(emp.City)
fmt.Println(emp.State)
}
Even though City belongs to Address,
it can be accessed directly through Employee.
Method Promotion with Embedding
Methods defined on embedded structs are automatically promoted to the outer struct.
func (a Address) FullAddress() string {
return a.City + ", " + a.State + ", " + a.Country
}
Now call it from Employee.
fmt.Println(emp.FullAddress())
This works because of method promotion through embedding.
Embedding vs Inheritance
In traditional inheritance:
- Child classes automatically inherit everything
- Tight coupling between parent and child
In Go embedding:
- Only selected behavior is reused
- Loose coupling
- Better flexibility
Multiple Embedding
A struct can embed multiple structs.
type Contact struct {
Email string
Phone string
}
type User struct {
Name string
Address
Contact
}
Now User has fields and methods from both embedded structs.
Real-World Use Cases
Embedding and composition are widely used in:
- HTTP request and response structures
- Database models
- Microservice architectures
- Configuration management
Many Go frameworks rely heavily on embedding for extensibility.
Best Practices
- Use composition to reuse functionality
- Use embedding only when field promotion makes sense
- Avoid deep embedding chains
- Design small, reusable structs
What’s Next?
In the next lesson, you will learn about Packages and Modules in Go, which help you organize large applications and manage dependencies professionally.