Original post

A very common question that comes up in forums is “how to I check that some
type implements a certain interface?”
. A common immediate reaction is that the
question makes no sense, because Go is statically typed, so the compiler
already knows
whether a type implements an interface or not. But it turns out
that the question in the general sense is more nuanced, and it’s worth spending
some time understanding the variations folks are usually interested in.

Let’s start with a basic example. Assume this Munger interface that has a
single Munge method:

type Munger interface {
    Munge(int)
}

And say that we have a type that doesn’t have a Munge method; for example,
int. If we try to do this:

var i int
var mm Munger = i

The compiler will rightfully complain:

cannot use i (type int) as type Munger in assignment:
    int does not implement Munger (missing Munge method)

The same happens if you attempt to pass i into a function that expects
a Munger, and so on.

So the gist of the common response is: you don’t need to perform this check,
the compiler will do it for you on first use.

A more deliberate compile-time check

It’s sometimes useful to have a more conscious compile-time check that a
certain type implements a certain interface. Think something similar to a
static_assert in C++. A nice trick to accomplish this is:

var _ Munger = (*Foo)(nil)

This statement checks if Foo implements Munger at compile time [1].
It can be placed on the top-level (outside functions) in a .go file, and
won’t generate any executable code in case the check passes. There are plenty of
examples of this pattern in the Go ecosystem; here’s one from the standard
library (io/multi.go):

var _ StringWriter = (*multiWriter)(nil)

After defining the multiWriter struct, the code checks if it implements
the StringWriter interface. This
can be useful to ensure that we get a clear compile error in an
expected place if the interface changes in some way.

The trick here is the usage of nil to create a typed value for the compiler
to see without declaring any explicit vars.

Run-time check

A more common request is checking whether a type implements an interface at
run-time
. Note that this is semantically different from what the compiler does
for us – we actually want to make a run-time decision based on what interfaces
a given type implements. This can be useful in many scenarios, such as testing,
plugins etc.

At first it seems easy – Go has good support for
type assertions, after all. But there’s
a problem. Suppose we have the Munger interface again, and some type
Foo; we want to check whether Foo implements Munger. A type
assertion would go like this:

var f Foo
_, ok := f.(Munger)

But the compiler complains:

invalid type assertion: f.(Munger) (non-interface type Foo on left)

This is because only values of interface types are allowed on the left-hand-side
of a type assertion. So what can we do? Well, if the compiler wants an
interface, we can give it an interface:

var f Foo
_, ok := interface{}(f).(Munger)

We start by converting f to the empty interface type. This conversion is
always successful because all types implement the empty interface. Now the
check will work and will return true if Foo implements Munger, and
false otherwise.

Run-time check using reflection

Another way to accomplish the run-time check is using reflection:

var f Foo

iMunger := reflect.TypeOf((*Munger)(nil)).Elem()
// ... now iMunger is a reflect.Type representing Munger

ok := reflect.TypeOf(&f).Implements(iMunger)

The reflect machinery has access to the underlying implementation of Go
objects and types at run-time, and it uses this information to answer queries
such as “does this type implement that interface”.

Note that this technique also uses the trick shown in the “deliberate
compile-time check section”, wherein a nil pointer is given a type in order
to avoid a temporary object.


[1] More precisely, it checks if *Foo implements Munger. But due
to the way Go automatically dereferences if needed, this must be true if
Foo implements Munger.