In Go programming, we use interfaces to store a set of methods without implementation. That is, methods of interface won't have a method body. For example,
type Shape interface {
area() float32
perimeter() float32
}
Here, Shape
is an interface with methods: area()
and perimeter()
. You can see both methods only have method signatures without any implementation.
Implementation of a Go Interface
You might be wondering what is the use of interface if the methods inside it don't have any implementations.
Well, to use an interface, we first need to implement it by a type (struct). To implement an interface, a struct should provide implementations for all methods of an interface. For example,
package main
import "fmt"
// interface
type Shape interface {
area() float32
}
// struct to implement interface
type Rectangle struct {
length, breadth float32
}
// use struct to implement area() of interface
func (r Rectangle) area() float32 {
return r.length * r.breadth
}
// access method of the interface
func calculate(s Shape) {
fmt.Println("Area:", s.area())
}
// main function
func main() {
// assigns value to struct members
rect := Rectangle{7, 4}
// call calculate() with struct variable rect
calculate(rect)
}
Output
Area: 28
Let's see how this program works:
Working on Interface Implementation
In the above example, we have created an interface named Shape
with a method area()
. Here, we are trying to implement this interface by the Rectangle
struct.
type Rectangle struct {
length, breadth float32
}
Now, to implement the interface, we have provided the implementation for getArea()
of the interface.
func (r Rectangle) area() float32 {
return r.length * r.breadth
}
To access this method, we have created a calculate()
method
// access method of the interface
func calculate(s Shape) {
fmt.Println("Area: ", s.area())
}
Here, the method takes a variable of Shape
named s
and uses it to call the area()
method.
Since the structure implements the interface, we have called calculate()
using the variable of structure
rect := Rectangle{7, 4}
calculate(rect)
Implement Go Interface by Multiple Structs
In Go, more than 1 struct can also implement a single interface. For example,
package main
import "fmt"
// interface
type Shape interface {
area() float32
}
// Rectangle struct implements the interface
type Rectangle struct {
length, breadth float32
}
// Rectangle provides implementation for area()
func (r Rectangle) area() float32 {
return r.length * r.breadth
}
// Triangle struct implements the interface
type Triangle struct {
base, height float32
}
// Triangle provides implementation for area()
func (t Triangle) area() float32 {
return 0.5 * t.base * t.height
}
// access method of the interface
func calculate(s Shape) float32 {
return s.area()
}
// main function
func main() {
// assigns value to struct members
r := Rectangle{7, 4}
t := Triangle{8, 12}
// call calculate() with struct variable rect
rectangleArea := calculate(r)
fmt.Println("Area of Rectangle:", rectangleArea)
triangleArea := calculate(t)
fmt.Println("Area of Triangle:", triangleArea)
}
Output
Area of Rectangle: 28 Area of Rectangle: 48
In the above example, we have used two structs: Rectangle
and Triangle
to implement the interface Shape
.
Just like before, both structs provide implementation for the area()
method.
Here, this time calculate()
calls the area()
using interface Shape
and returns it.
So, for the first call, calculate(r)
, the method will call the area()
method implementation of Rectangle
. Similarly, for calculate(t)
, the method will call the area()
method implementation of Triangle
.
What happens if the struct doesn't implement all methods of interface?
When a struct implements an interface, it should provide an implementation for all the methods of the interface. If it fails to implement any method, we will get an error. For example,
package main
import "fmt"
// interface
type Shape interface {
area() float32
perimeter() float32
}
// Rectangle struct implements the interface
type Rectangle struct {
length, breadth float32
}
// Rectangle provides implementation for area()
func (r Rectangle) area() float32 {
return r.length * r.breadth
}
// access method of the interface
func calculate(s Shape) float32 {
return s.area()
}
// main function
func main() {
// assigns value to struct members
r := Rectangle{7, 4}
// call calculate() with struct variable rect
rectangleArea := calculate(r)
fmt.Println("Area of Rectangle:", rectangleArea)
}
Output
cannot use r (type Rectangle) as type Shape in argument to calculate: Rectangle does not implement Shape (missing perimeter method)
In the above example, the Shape
interface has two methods: area()
and perimeter()
. Here, we are trying to implement the interface by the Rectangle
struct.
However, the struct only provides an implementation for the area()
. Since the struct doesn't implement all the methods of the interface, we get an error.