In Go, interfaces are implemented implicitly, meaning that the developer doesn’t need to declare the interfaces it implements. While this is usually very convenient, there are cases where you might want to explicitly check the implementation of an interface.
The best way to do that is to rely on the compiler.
Imagine that we have the following code:
package main type Jedi interface { HasForce() bool } type Knight struct {} func main() {} |
The code compiles, but we would like to enforce that our Knight
type implements the Jedi
interface. We could of course write tests for that, but there is a better way to ensure that the interface is implemented, a way that will prevent our code from compiling.
package main type Jedi interface { HasForce() bool } type Knight struct { } var _ Jedi = (*Knight)(nil) func main() { } |
Compiling the code above gives us the following error:
cannot use (*Knight)(nil) (type *Knight) as type Jedi in assignment:
*Knight does not implement Jedi (missing HasForce method)
cannot use (*Knight)(nil) (type *Knight) as type Jedi in assignment:
*Knight does not implement Jedi (missing HasForce method)
The magic happens in var _ Jedi = (*Knight)(nil)
. We are declaring a variable named _
(underscore), meaning that we don’t care about the variable itself, nor its value. We declare that the type of this variable is Jedi
, which is the interface that we want to ensure is being implemented by our struct type. The other side of the =
sign might seem a little more cryptic. It creates a nil
value of type *Knight
(pointer to Knight). In order for this to compile, the pointer in question must satisfy the Jedi
interface. Because that is not the case yet, the compiler fails.
Implementing the interface gets rid of the compiler error:
package main type Jedi interface { HasForce() bool } type Knight struct { } func (k *Knight) HasForce() bool { return true } var _ Jedi = (*Knight)(nil) func main() { } |
Explore royalty-free sounds from leading artists, producers, and sound designers:
July 3, 2014