function as an interface

“An interface type is defined as a set of method signatures.”

Taking a simple example:

1
2
3
type Fooer interface {
    Foo(input string) string
}

golang nameing convention is interfaces that end in er, Reader, Writer, Closer etc..

In this example, the interface Fooer defines a single method Foo, any struct with a method Foo will implement this interface, (implementation is done implicitly).

1
2
3
4
5
type aFoo struct {}

func (aFoo) Foo(input string) string {
    return "foo: " + input
}

But it’s not just structs that can implement interfaces, if an interface has a single method, then you can implement it with a function type.

1
2
3
4
5
type bFoo func(input string) string

func (f bFoo) Foo(input string) string {
	return f(input)
}

But why? If you define your more complex behaviours and interfaces by embedding smaller interfaces with smaller method sets, then creating the implementations of those interfaces becomes significantly easier. You can now mock or implemet behaviours with an anonymous function instead of a mock or no op struct.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
type Fooer interface {
	Foo(input string) string
}

type bFoo func(input string) string

func (f bFoo) Foo(input string) string {
	return f(input)
}

func newFooer() Fooer {
	return bFoo(func(in string) string { return "foo: " + in })
}

Here the type bFoo implemets the interface Fooer and any anonymous function that has the same method signature as Fooer can be cast to bFoo and it too will implement the Fooer interface. This means less code and cleaner code as once you have the type bFoo any function can implement Fooer without the need for a struct for it to be a method upon.

Runnable example: https://play.golang.org/p/bVp8Lljxkj

Now if you have a complex struct like:

1
2
3
4
5
6
type FooBar struct {
    foo Fooer
    bar Barer
    baz Bazer
    qux Quxer
}

You can implement the foo Fooer field with just an anonymous function.