Go Composition over Inheritance 🎯

beginner
14 min

Go Composition over Inheritance 🎯

Welcome to a comprehensive guide on the principle of Composition over Inheritance in Go! This lesson is perfect for both beginners and intermediates. Let's dive into understanding why this concept is essential in Go programming, and how to apply it effectively.

What is Composition? 📝

Composition is a way of combining classes and objects to form more complex structures. It allows for creating reusable and modular code by assembling objects of existing classes. This technique promotes loose coupling, making your code more flexible and easier to maintain.

Why Composition over Inheritance? 💡

Inheritance has its limitations. For instance, it can lead to a tight coupling between classes, making changes in one class affecting others. Composition, on the other hand, helps to avoid these issues, promoting code modularity and reusability.

Understanding Composition in Go 📝

Go does not support classical inheritance, but it provides an elegant solution for achieving similar results using composition and interfaces. Let's explore this through an example.

Example: Car Composition 🚗

go
type Engine interface { Start() Stop() } type Wheel interface { Rotate() } type Car struct { Engine Wheels []Wheel } type CarEngine struct { name string start func() stop func() } func (ce *CarEngine) Start() { ce.start() } func (ce *CarEngine) Stop() { ce.stop() } type CarWheel struct { name string rotate func() } func (cw *CarWheel) Rotate() { cw.rotate() } func main() { engine := &CarEngine{ name: "V6", start: func() { fmt.Println("Engine started.") }, stop: func() { fmt.Println("Engine stopped.") }, } wheels := []Wheel{ &CarWheel{ name: "Front left", rotate: func() { fmt.Println("Front left wheel rotating.") }, }, &CarWheel{ name: "Front right", rotate: func() { fmt.Println("Front right wheel rotating.") }, }, &CarWheel{ name: "Rear left", rotate: func() { fmt.Println("Rear left wheel rotating.") }, }, &CarWheel{ name: "Rear right", rotate: func() { fmt.Println("Rear right wheel rotating.") }, }, } car := &Car{ Engine: engine, Wheels: wheels, } car.Engine.Start() for _, wheel := range car.Wheels { wheel.Rotate() } car.Engine.Stop() }

In this example, we have created a Car structure, which uses an engine (Engine interface) and an array of wheels (Wheel interface). Instead of inheriting these functionalities directly, we create separate structures for the engine and wheels and assign the necessary methods to them. This demonstrates the power of composition in Go.

Quick Quiz
Question 1 of 1

What is the key benefit of using Composition over Inheritance in Go?

Wrapping Up 💡

In this lesson, you've learned the basics of Composition over Inheritance in Go. By understanding the power of composition, you'll be able to write cleaner, more modular code that is easier to maintain and scale. Happy coding! 🚀