Go Interface Composition 🎯

beginner
15 min

Go Interface Composition 🎯

Welcome to the exciting world of Go Interface Composition! In this lesson, we'll learn how to create powerful and flexible programs using interfaces and composition in Go. Let's get started!

What are Interfaces in Go? 📝

An interface in Go is a collection of methods that specify a behavior but don't provide any implementation. Interfaces allow us to define a contract that a type must fulfill, making it easier to write modular, reusable code.

go
type Shape interface { Area() float64 }

In the example above, Shape is an interface with a single method Area() float64.

Understanding Composition 💡

Composition, also known as aggregation, is a design principle that allows us to create complex types by combining simpler types. In Go, we can use interfaces and type embedding to achieve composition.

go
type Circle struct { Radius float64 } func (c Circle) Area() float64 { return 3.14 * c.Radius * c.Radius } func (c Circle) Diameter() float64 { return 2 * c.Radius }

In the example above, Circle is a struct that implements the Shape interface by defining the Area() method. We can also define additional methods specific to the Circle type.

Interface Composition 🎯

Now let's see how interfaces and composition work together. In Go, we can define an interface that contains multiple methods, and types can implement any number of these methods.

go
type Drawable interface { Draw() Info() string } type Circle struct { Radius float64 } func (c Circle) Draw() { fmt.Println("Drawing a circle with radius", c.Radius) } func (c Circle) Info() string { return fmt.Sprintf("Circle with radius: %f", c.Radius) } type Square struct { Side float64 } func (s Square) Draw() { fmt.Println("Drawing a square with side", s.Side) } func (s Square) Info() string { return fmt.Sprintf("Square with side: %f", s.Side) }

In the example above, we have defined an Drawable interface with two methods: Draw() and Info(). Both Circle and Square types implement the Drawable interface by defining their own implementations of the methods.

Practical Example 💡

Let's create a simple application that draws shapes and displays information about them.

go
package main import ( "fmt" ) type Shape interface { Area() float64 } type Drawable interface { Draw() Info() string } type Circle struct { Radius float64 } func (c Circle) Area() float64 { return 3.14 * c.Radius * c.Radius } func (c Circle) Draw() { fmt.Println("Drawing a circle with radius", c.Radius) } func (c Circle) Info() string { return fmt.Sprintf("Circle with radius: %f", c.Radius) } type Square struct { Side float64 } func (s Square) Area() float64 { return s.Side * s.Side } func (s Square) Draw() { fmt.Println("Drawing a square with side", s.Side) } func (s Square) Info() string { return fmt.Sprintf("Square with side: %f", s.Side) } func main() { circle := Circle{Radius: 5.0} square := Square{Side: 4.0} shapes := []Drawable{circle, square} for _, shape := range shapes { fmt.Println(shape.Info()) shape.Draw() fmt.Println("Area:", shape.(Shape).Area()) fmt.Println() } }

In the example above, we have defined two interfaces: Shape and Drawable. Both Circle and Square types implement both interfaces. We then create a list of shapes, iterate over them, and call their Info(), Draw(), and Area() methods.

Quiz 🎯

Quick Quiz
Question 1 of 1

What is the purpose of an interface in Go?

That's it for this lesson on Go Interface Composition! In the next lesson, we'll dive deeper into Go interfaces and explore some advanced concepts. Happy learning! 🌟