Go is a statically-typed language with a strong emphasis on simplicity, efficiency, and readability. One of the key features of Go is its ability to define and use interfaces, which provide a way to specify the behavior of an object without requiring a specific implementation.

An interface is a defined set of method signatures - that is, it lets us know what methods must exist for a certain type.

If you come from the OOP world this may be familiar to you where interfaces can define what methods a class must have.

We can also use them in Golang.

An example of an interface that has many implementations is the io.Reader interface.

type Reader interface {
  Read(p []byte) (n int, err error)
}

Here we can see that:

  • there must be a Read method to be used as a Reader
  • that Read method must take a byte slice
  • and, it must return both an integer and an error

A Practical Example

We can create our own interface like this:

type Dog interface {
  Bark() string
}

Then we can have multiple dogs that bark in different ways.

First let’s create the structs for the different types of dog:

type smallDog struct {}
type bigDog struct {}
type snoopDogg struct {}

Then let’s make them bark in different ways:

func (d smallDog) Bark() string {
    return "yap!"
}
func (d bigDog) Bark() string {
    return "woof!"
}
func (d snoopDogg) Bark() string {
    return "fo shizzle!"
}

Then in our func main() let’s call the different bark methods:

func main() {
    small := smallDog{}
    big := bigDog{}
    snoop := snoopDogg{}

    fmt.Println("Small dog says,", small.Bark())
    fmt.Println("Big dog says,", big.Bark())
    fmt.Println("Snoop Dogg says,", snoop.Bark())
}

Output:

Small dog says, yap!
Big dog says, woof!
Snoop Dogg says, fo shizzle!

For the complete code check out: Basic Interface Gist