How to Check nil Interface in Golang?

Simplify Complexity
2 min readMay 15, 2022

It’s not a good idea to check an interface for nil.

Try the following code:

type user interface{}
type staff struct{}
func compareNil() {
var generic user
generic = nil
// works as expected
fmt.Printf("value=%v type=%T (generic==nil)=%v\n", generic, generic, generic == nil)
generic = (*staff)(nil) // fails my expectation
fmt.Printf("value=%v type=%T (generic==nil)=%v\n", generic, generic, generic == nil)
}

go playground: https://play.golang.org/p/7J9DeIjgNia

Output

value=<nil> type=*main.staff (generic==nil)=false
value=<nil> type=<nil> (generic==nil)=true

Why interface check for nil is special

An interface is a tuple of [Value, Type]. The nil interface is a tuple [nil, nil]. However, the above code is an interface containing [nil, *main.staff] which is not nil.

We can check for nil as follows:

func isNil(i interface{}) bool {                        
return i == nil || reflect.ValueOf(i).IsNil()
}

Here i==nil means i has [nil, nil] or has a nil value in [nil, *main.staff].

But if the interface points to a type that has no Nil value:

s := "hello"
generic = s
fmt.Printf("value=%v type=%T type=%v\n", generic, generic, reflect.ValueOf(generic).IsNil())

The code panics:

panic: reflect: call of reflect.Value.IsNil on string Valuegoroutine 1 [running]:
reflect.Value.IsNil(...)
/Users/xxx/.goenv/versions/1.14.0/src/reflect/value.go:1063
main.compareNil()
/Users/xxx/go/1.14.0/src/mygo/interfaces/interfaces.go:48 +0x3b1
main.main()
/Users/xxx/go/1.14.0/src/mygo/interfaces/interfaces.go:29 +0x142
exit status 2

Conclusion

The safest way to compare nil interfaces is switch on various types, the interface can assume. Never check as myinterface == nil.

References

Simplify Complexity

Golang, Distributed Systems, File Systems, Python, C/C++, Linux