What is an Interface?

An interface is something I first stumbled upon when I started learning compiled languages. I had read the term a couple of times before, but really only with C, Java and lately Go an interface actually means something to me that I can remember.

I've used the abbreviation API about one thousand times in my life, which stands for Application programming interface, usually I mean web APIs, where I get some JSON to feed it to my frontend or something, but that's already a very specific use case.

As with many words in computer science, interface can mean many things, but depending on context it means a very specific thing. To quote wikipedia:

In computing, an interface is a shared boundary across which two or more separate components of a computer system exchange information.

and more specifically regarding programming:

the term interface is used to define an abstract type that contains no data but defines behaviours as method signatures.

So an interface is a bit like a puzzle piece. You can't just attach your code or your function anywhere, but you need to find the right part that's sticking out.

Implementing / Satisfying Intefaces

To implement or to satisfy an interface means to comply with the rules set by the blueprint. In object oriented languages such as C# or Java, interfaces are abstract classes, that just set some requirements for which functions must be included and which types they can receive or return.

Since Golang is not an object oriented language, there are no classes to implement, but we can still satisfy an interface with our type and it will be checked automatically by the compiler. Let's pretend we are programming a series of vending machines and instead of a <Product> type, they're supposed to return a string:

package main

import "fmt"

type VendingMachine interface {
    ReturnItem() string
}

type Cola struct {
}

func (d Cola) ReturnItem() string {
    return "you get a cooled cola"
}

func main() {
    var vend1 VendingMachine
    vend1 = Cola{}
    fmt.Println(vend1.ReturnItem())
}

You can see that type VendingMachine interface creates the first blueprint interface and the Cola struct now will need to satisfy the interface by also having a ReturnItem function.

We test this by creating a variable vend1 of type VendingMachine and assign a Cola struct to it.

The expected output is: you get a cooled cola

If we remove the following code:

func (d Cola) ReturnItem() string {
    return "you get a cooled cola"
}

We get the error:

# command-line-arguments
./main.go:21:8: cannot use Cola literal (type Cola) as type VendingMachine in assignment:
        Cola does not implement VendingMachine (missing ReturnItem method)

Thanks Go! Helpful! This way we can't forget the essential ReturnItem function in our VendingMachine and make our customers really angry at us, because no products come out after they payed.

Similarly, if we change the return type of the Cola ReturnItem to int:

./main.go:13:9: cannot use "you get a cooled cola" (type string) as type int in return argument
./main.go:25:8: cannot use Cola literal (type Cola) as type VendingMachine in assignment:
        Cola does not implement VendingMachine (wrong type for ReturnItem method)
                have ReturnItem() int
                want ReturnItem() string

This makes sure that we return the correct type as well, because the humans or possibly robots interfacing with our vending machine will expect strings, not integers to come out.

Lastly, when coming from other languages you might try to implement a go interface by using the interface to create a type instance, maybe like this:

vend1 := VendingMachine{Cola{}}

However, since the implements checking is done by the compiler and abstracted away, you'll only get an error about a composite literal:

./main.go:17:25: invalid type for composite literal: VendingMachine

Summary

Interfaces are handy tools to ensure that your application can have consistently grouped functionalities with different values, even in a non OOP language like Go.

Real world examples of interfaces are the Readers and Writers in Go are IO parts like the Writer or Reader which you can try out and extend for some simple file system operations if you're interested.

Tagged with: #go #golang

Thank you for reading! If you have any comments, additions or questions, please tweet or toot them at me!