Interfaces in Go

Lets first define two types, circle and rectangle. Both types have the method area().

package main

import (
	"fmt"
	"math"
)

type circle struct {
	radius float64
}

type triangle struct {
	base   float64
	height float64
}

func (t triangle) area() float64 {
	return 0.5 * t.base * t.height
}

func (c circle) area() float64 {
	return math.Pi * c.radius * c.radius
}


func main() {

	t := triangle{
		base:   10.0,
		height: 22.0,
	}
	c := circle{
		radius: 10,
	}

	fmt.Printf("Triangle area = : %f\n", t.area())
	fmt.Printf("Circle area = : %f", c.area())

}

In main() both objects t, c are created then the area() method is called on each.

What if we wanted to loop over those objects? We cannot create a slice as t, c are of different types, and a slice must contain objects of the same type. This is where interfaces come in.

We can define an interface shape as follows:

type shape interface {
	area() float64
}

Now where ever we have a type that has an area() method we can say these types implement the interface. A better way to think of it -> think of the interface as a higher level type for, in this case, triangle and circle.

An interface then allows the following:

shapes := []shape{t, c}
for _, s := range shapes {
	fmt.Println(s.area())
}

Extending this slightly, we can get to something like this -> the interface has been extended as have each of the types to include the getname() method. Then a slice of type shape is created, the objects are instantiated and then iterated over to get the object name and area.

package main

import (
	"fmt"
	"math"
)

type shape interface {
	area() float64
	getname() string
}

type circle struct {
	radius float64
	name   string
}

type triangle struct {
	base   float64
	height float64
	name   string
}

func (t triangle) area() float64 {
	return 0.5 * t.base * t.height
}

func (t triangle) getname() string {
	return t.name
}

func (c circle) area() float64 {
	return math.Pi * c.radius * c.radius
}

func (c circle) getname() string {
	return c.name
}

func main() {

	shapes := []shape{
		triangle{base: 10, height: 20, name: "my triangle"},
		circle{radius: 10, name: "my circle"},
	}
	for _, s := range shapes {
		fmt.Printf("%s has an area of %f\n", s.getname(), s.area())
	}

}

And that’s it!

Leave a comment