Understanding Inheritance in Golang
James Reed
Infrastructure Engineer · Leapcell

Key Takeaways
- Golang does not support traditional inheritance but uses struct embedding for code reuse.
- Method overriding can be achieved by defining methods with the same name in embedded structs.
- Interfaces enable polymorphism, allowing different types to share common behaviors.
Inheritance is a fundamental concept in object-oriented programming (OOP), allowing one class to acquire the properties and behaviors of another. However, Golang (Go) does not support traditional class-based inheritance as found in languages like Java or C++. Instead, Go uses composition and interface embedding to achieve similar functionality.
Composition Over Inheritance
In Go, struct embedding is the primary mechanism to achieve inheritance-like behavior. Instead of using a class-based hierarchy, Go encourages composition, where a struct can include another struct to reuse its fields and methods.
Example of Struct Embedding
package main import "fmt" // Base struct type Person struct { Name string Age int } // Method for Person func (p Person) Greet() { fmt.Printf("Hello, my name is %s.\n", p.Name) } // Employee struct embedding Person type Employee struct { Person Position string } func main() { emp := Employee{ Person: Person{Name: "Alice", Age: 30}, Position: "Engineer", } // Accessing fields of embedded struct directly fmt.Println(emp.Name) // Alice fmt.Println(emp.Age) // 30 fmt.Println(emp.Position) // Engineer // Calling method from embedded struct emp.Greet() // Hello, my name is Alice. }
Here, Employee
embeds Person
, which allows it to inherit its fields and methods without explicit subclassing. The Greet()
method of Person
is accessible from Employee
because of embedding.
Overriding Methods in Embedded Structs
While Go does not have explicit method overriding, you can achieve a similar effect by defining a method with the same name in the embedding struct, which takes precedence.
package main import "fmt" type Person struct { Name string } func (p Person) Greet() { fmt.Println("Hello from Person") } type Employee struct { Person } // Overriding the Greet method func (e Employee) Greet() { fmt.Println("Hello from Employee") } func main() { emp := Employee{Person: Person{Name: "Bob"}} emp.Greet() // Hello from Employee }
In this case, Employee
defines its own Greet()
method, which overrides the one from Person
when called on an Employee
instance.
Using Interfaces for Polymorphism
Go supports polymorphism through interfaces. By defining an interface and implementing it in different structs, we can achieve behavior similar to inheritance.
package main import "fmt" type Greeter interface { Greet() } type Person struct { Name string } func (p Person) Greet() { fmt.Printf("Hello, I am %s.\n", p.Name) } type Robot struct { Model string } func (r Robot) Greet() { fmt.Printf("Beep boop, I am %s.\n", r.Model) } func SayHello(g Greeter) { g.Greet() } func main() { p := Person{Name: "Alice"} r := Robot{Model: "X100"} SayHello(p) // Hello, I am Alice. SayHello(r) // Beep boop, I am X100. }
Here, both Person
and Robot
implement the Greeter
interface by defining a Greet()
method. The SayHello
function works with any type that implements Greeter
, showcasing Go’s way of achieving polymorphism.
Conclusion
While Go does not support classical inheritance, it provides powerful mechanisms like struct embedding and interfaces to promote code reuse and polymorphism. By favoring composition over inheritance, Go ensures better maintainability and flexibility in structuring programs.
FAQs
No, Golang relies on struct embedding and interfaces instead of traditional inheritance.
You define a method with the same name in the embedding struct, which takes precedence.
Interfaces enable polymorphism, allowing different types to implement the same behavior without direct inheritance.
We are Leapcell, your top choice for hosting Go projects.
Leapcell is the Next-Gen Serverless Platform for Web Hosting, Async Tasks, and Redis:
Multi-Language Support
- Develop with Node.js, Python, Go, or Rust.
Deploy unlimited projects for free
- pay only for usage — no requests, no charges.
Unbeatable Cost Efficiency
- Pay-as-you-go with no idle charges.
- Example: $25 supports 6.94M requests at a 60ms average response time.
Streamlined Developer Experience
- Intuitive UI for effortless setup.
- Fully automated CI/CD pipelines and GitOps integration.
- Real-time metrics and logging for actionable insights.
Effortless Scalability and High Performance
- Auto-scaling to handle high concurrency with ease.
- Zero operational overhead — just focus on building.
Explore more in the Documentation!
Follow us on X: @LeapcellHQ