🧩 Go Structs, Interfaces & Composition – Build Reusable and Type-Safe Programs
🧲 Introduction – Why Use Structs & Interfaces in Go?
Go is a statically typed language without classical inheritance. Instead, it promotes composition over inheritance through powerful features like structs, interfaces, and embedding. These allow you to build flexible, reusable, and type-safe applications while avoiding complexity.
🎯 In this guide, you’ll learn:
- How to define and use structs in Go
- How interfaces enable polymorphism and abstraction
- What type assertions are and how to use them safely
- How Go supports composition-based reuse (struct embedding)
📘 Topics Covered
| 🔹 Concept | 📖 Description |
|---|---|
| 🏗️ Go Structs | Custom data types that group related fields |
| 🧩 Go Interfaces | Define method sets for polymorphic behavior |
| 🔍 Go Type Assertion | Safely convert an interface value back to its concrete type |
| 🧬 Go Inheritance via Composition | Simulate inheritance using struct embedding |
🏗️ Go – Structs
🔹 Define & Use
type Person struct {
Name string
Age int
}
func main() {
p := Person{Name: "Alice", Age: 30}
fmt.Println(p.Name) // Alice
}
✅ Update Struct Fields
p.Age = 31
✅ Structs are passed by value. Use pointers to modify them inside functions:
func update(p *Person) {
p.Age = 40
}
🧩 Go – Interfaces
An interface defines behavior without implementation:
type Shape interface {
Area() float64
}
type Circle struct {
Radius float64
}
func (c Circle) Area() float64 {
return 3.14 * c.Radius * c.Radius
}
🔹 Interface in Action
func printArea(s Shape) {
fmt.Println("Area:", s.Area())
}
✅ Any type that implements all methods of an interface implicitly satisfies it—no need for implements.
🔍 Go – Type Assertion
Type assertions let you access the underlying type of an interface:
var i interface{} = "Hello"
s := i.(string) // assert it's a string
fmt.Println(s)
🧠 Safe Assertion
val, ok := i.(string)
if ok {
fmt.Println("It's a string:", val)
} else {
fmt.Println("Not a string")
}
✅ Prevents panic on invalid assertions.
🧬 Go – Inheritance via Composition (Struct Embedding)
Go doesn’t support classical OOP inheritance. Instead, it uses embedding:
type Animal struct {
Name string
}
func (a Animal) Speak() {
fmt.Println(a.Name, "makes a sound")
}
type Dog struct {
Animal
Breed string
}
🔹 Use Embedded Methods
d := Dog{Animal: Animal{Name: "Rex"}, Breed: "Labrador"}
d.Speak() // Rex makes a sound
✅ Fields and methods of the embedded struct are promoted to the outer struct.
📌 Summary – Recap & Next Steps
Go’s struct-interface system promotes clarity, safety, and reusability. Instead of inheritance, you build powerful programs through interface abstraction and composition, keeping your code loosely coupled and easily testable.
🔍 Key Takeaways:
- Structs group fields under custom types
- Interfaces enable polymorphism without OOP complexity
- Type assertions safely extract values from interfaces
- Composition (struct embedding) simulates inheritance in Go
⚙️ Real-World Applications:
- Defining request/response models in APIs
- Implementing strategy or behavior patterns
- Building plugin-like systems via interface injection
- Mocking and testing with interfaces
❓ Frequently Asked Questions
❓ Does Go support inheritance like Java or C++?
✅ ❌ No. Go encourages composition over inheritance using struct embedding.
❓ Can a struct implement multiple interfaces?
✅ Yes. A struct can implement as many interfaces as needed:
type Reader interface { Read() }
type Writer interface { Write() }
type File struct{}
func (f File) Read() {}
func (f File) Write() {}
❓ What’s the zero value of an interface?
✅ nil. An interface without any value or method is nil.
❓ How do I test if a value implements an interface?
✅ Use:
var s Shape = Circle{Radius: 5}
_, ok := interface{}(s).(Shape)
❓ Can I embed multiple structs in one struct?
✅ Yes. Embedded fields are promoted:
type Engine struct{}
type Wheels struct{}
type Car struct {
Engine
Wheels
}
Share Now :
