Shine on you crazy interface

Go's interfaces are brilliant. It's not immediately apparent and at first can be confusing, but after a while its brilliance shines through.

TL;DR - if a concrete type has the necessary behavior (methods) to satisfy an interface, it can implicitly implement that interface.

In Go, interfaces are considered abstract types, meaning we do not know what an interface really is, only what it can do.

The Go standard library makes use of interfaces, let's take a look at an example. Say we have the following (see it in the Go Playground):

type song struct {
    name    string
    release time.Time

type songs []song

func (s songs) String() string {
    var ss []string
    for i := range s {
        ss = append(ss, s[i].name+" "+fmt.Sprint(s[i].release.Year()))
    return strings.Join(ss, ", ")

s := songs{
    {"Comfortably Numb", time.Date(1979, time.November, 0, 0, 0, 0, 0, time.UTC)},
    {"Interstellar Overdrive", time.Date(1967, time.August, 0, 0, 0, 0, 0, time.UTC)},
    {"Time", time.Date(1973, time.March, 0, 0, 0, 0, 0, time.UTC)},
    {"High Hopes", time.Date(1994, time.March, 0, 0, 0, 0, 0, time.UTC)},

// Comfortably Numb 1979, Interstellar Overdrive 1967, Time 1973, High Hopes 1994

Say we want to sort the above based on release date so we can listen to Pink Floyd in chronological order. We could write our own sorting function, but instead, let's see if we can implement the sort.Sort from the standard library:

func Sort(data Interface)
// where Interface is an abstract type that has three methods
type Interface interface {
    // comments omitted for brevity
    Len() int
    Less(i, j int) bool
    Swap(i, j int)

So to implement sort.Interface we write the following three methods for our songs type:

func (s songs) Len() int {
    return len(s)

func (s songs) Less(i, j int) bool {
    return s[i].release.Before(s[j].release)

func (s songs) Swap(i, j int) {
    s[i], s[j] = s[j], s[i]

The sort.Sort function doesn't care about the underlying type. So long as the type has behavior through its methods that implements Len, Less and Swap it can be sorted... (usually)

// Interstellar Overdrive 1967, Time 1973, Comfortably Numb 1979, High Hopes 1994

Note as of Go 1.8 it's even easier to implement slice sort. See go1.8#sort_slice

Example can be found here:

// to implement sort.Slice all we need is the Less method from above, omit Len and Swap entirely
// func Slice(slice interface{}, less func(i, j int) bool)

sort.Slice(s, s.Less)
// Interstellar Overdrive 1967, Time 1973, Comfortably Numb 1979, High Hopes 1994

To wrap things up, we were able to leverage a standard library sorting function through an interface. Our concrete type songs implicitly implemented the sort.Sort function because it had the necessary behavior (methods). The interface type sort.Interface defined the contract between sort.Sort and its caller.

These are the types of quality of life improvements that make Go a joy to work with.