Interfaces
Interfaces are a way to define a set of methods that a type must implement.
They are a powerful feature of Go, and they are used to define contracts between types.
Why do we need interfaces?
Well, let's say we want to create an array of Courses and Workshops, so we can iterate and print them.
We run into a problem.
var courses [2]Course
courses[0] = goCourse
courses[1] = goWorkshop // error
for _, c := range courses {
fmt.Println(c)
}
The same type problem occurs when we want to create a function that can receive both Courses and Workshops. Like for instance a function SignUp()
.
To get around this, we create an interface. Let's call it Signable
.
type Signable interface {
SignUp() string
}
Interfaces define a set of methods that a type must implement in order to fulfil the contract.
This is how the Course
and Workshop
method implementations would look like:
func (c Course) SignUp() string {
return fmt.Sprintf("Signed up for the course %s", c.Name)
}
func (w Workshop) SignUp() string {
return fmt.Sprintf("Signed up for the workshop %s", w.Name)
}
And this this would work, since both Course
and Workshop
implement the Signable
interface:
var courses [2]Signable
courses[0] = goCourse
courses[1] = goWorkshop
for _, c := range courses {
fmt.Println(c)
}
This may seem confusing, since we are not explicitly saying that Course
and Workshop
implement the Signable
interface.
In Go, implementation is implicit. If a type has the methods defined in the interface, it implements the interface.
What we have just done is also known as polymorphism.