Go tip of the week: How to trivially test interface values for nil
A common foot sling for Go newcomers are interface variables that get a nil pointer value assigned. While that interface now contains a pointer value that is nil, the interface variable itself is not nil.
Here is what I mean: The following code snippet
- creates
x
as a pointer to an integer that isnil
by default, - creates
y
as an empty interface that is alsonil
by default, - and assigns
x
toy
.
var x *int
var y any
y = x
Now the interface variable y
is not nil
anymore, because we assigned a variable to it. However, the variable, x
, is still nil
.
Pop quiz: what does y == nil
yield? true
or false
?
An interface is like a struct with a nillable field
A common misconception is that an interface transparently represents the value that got assigned to it, hence y == nil
would yield true
. That's not the case.
Think of the interface as a container for the value, similar to a struct. If you create a struct with a pointer field, it seems quite natural that the struct is not nil
, regardless whether the contained field is nil
or not.
type Z struct {
x *int
}
var x *int
var z Z
z.x = x
The field selector z.x
makes it pretty obvious that we don't assign nil
to the whole struct. With an interface, this circumstance is not that obvious. But technically, both scenarios are quite close together.
How to test the value behind an interface for nil
So our interface y
is not nil
, but the value it holds is nil
. How can we test that value for nilness?
Eeezee!
All it take is to type-assert the true type of the value assigned to the interface. In other words, type-assert the type of x
. With this “one weird trick that makes even CommonLisp diehards envious” (spoiler alert: I bet they don't even care), we can drill down to the value the interface holds and compare it against nil
:
y.(*int) == nil
Bitte sehr! Run the code on the
Go Playground, and try the same
with a non-nil
pointer.