๐ŸŽ“ A1Learner
๐Ÿ”

Go Interfaces

An interface is a type that names a set of methods. A value of any type with those methods can be stored in the interface.

Satisfy an Interface

Shape names one method, Area. Square has that method, so a Square fits in a Shape value.

package main

import "fmt"

type Shape interface {
	Area() int
}

type Square struct {
	Side int
}

func (s Square) Area() int {
	return s.Side * s.Side
}

func main() {
	var shape Shape = Square{Side: 4}
	fmt.Println(shape.Area())
}

A Slice of an Interface

One slice holds a Square and a Rectangle. Each value answers Area in its own way.

package main

import "fmt"

type Shape interface {
	Area() int
}

type Square struct {
	Side int
}

func (s Square) Area() int {
	return s.Side * s.Side
}

type Rectangle struct {
	Width  int
	Height int
}

func (r Rectangle) Area() int {
	return r.Width * r.Height
}

func main() {
	shapes := []Shape{Square{Side: 3}, Rectangle{Width: 2, Height: 5}}
	for _, shape := range shapes {
		fmt.Println(shape.Area())
	}
}

Assert a Type

The assertion asks whether the Shape value holds a Square. The ok value reports the answer.

package main

import "fmt"

type Shape interface {
	Area() int
}

type Square struct {
	Side int
}

func (s Square) Area() int {
	return s.Side * s.Side
}

func main() {
	var shape Shape = Square{Side: 5}
	square, ok := shape.(Square)
	if ok {
		fmt.Println(ok)
		fmt.Println(square.Side)
	}
}

The Empty Interface

An empty interface value can hold any type. This slice holds an int and a string.

package main

import "fmt"

func main() {
	values := []interface{}{42, "hello"}
	for _, value := range values {
		fmt.Println(value)
	}
}

Example

package main

import "fmt"

type Shape interface {
	Area() int
}

type Square struct {
	Side int
}

func (s Square) Area() int {
	return s.Side * s.Side
}

type Rectangle struct {
	Width  int
	Height int
}

func (r Rectangle) Area() int {
	return r.Width * r.Height
}

func main() {
	shapes := []Shape{Square{Side: 4}, Rectangle{Width: 3, Height: 5}, Square{Side: 2}}
	total := 0
	for _, shape := range shapes {
		fmt.Println(shape.Area())
		total += shape.Area()
	}
	fmt.Println("Total:", total)
}

Key points

  • Interface: a type that names a set of methods.
  • A type satisfies an interface just by having its methods.
  • An interface value can hold any type that satisfies it.
  • Type assertion: an expression that gets the concrete value out of an interface.
  • The ok form of an assertion reports whether the value has the named type.
  • The empty interface is written interface{} and holds values of any type.

In this example, the slice holds two Squares and one Rectangle as Shape values. The loop prints the area of each shape in slice order. The same loop adds each area into total. The areas 16, 15, and 4 add up to the printed total of 35.

Note

The empty interface names no methods, so every type satisfies it.

Try it Yourself

Edit the code, then press Run.

Running is simulated ยท Go Playground

Exercise

What makes a type satisfy an interface in Go?