Checking for a nil
value is very common in GO programs so it is important to know the difference between checking nil
on a given type and checking nil
on an interface{}
object.
Let's start with an example:
package main
import "fmt"
func GiveMeANil(value *string) {
if value == nil {
fmt.Println("Thank you my friend! I really needed it!")
} else {
fmt.Println("Sorry mate, but I really need a nil...")
}
}
func main() {
// explicitly assigning `nil` for clarity
var nilString *string = nil
GiveMeANil(nilString)
GiveMeANil(nil)
}
==== OUTPUT ====
Thank you my friend! I really needed it!
Thank you my friend! I really needed it!
No surprises. The code is doing exactly what we were expecting it to do.
However, now we notice that the GiveMeANil
function is so useful that we want it to work with any type, so we decide to change the code using interface{}
package main
import "fmt"
func GiveMeANil(value interface{}) {
if value == nil {
fmt.Println("Thank you my friend! I really needed it!")
} else {
fmt.Println("Sorry mate, but I really need a nil...")
}
}
func main() {
// explicitly assigning `nil` for clarity
var nilString *string = nil
GiveMeANil(nilString)
GiveMeANil(nil)
}
==== OUTPUT ====
Sorry mate, but I really need a nil...
Thank you my friend! I really needed it!
The output has changed. For some reason, GO is saying the first nil
is not a nil
. Why?
The reason is that an interface{}
internally is an object composed of 2 attributes (type
and the value
) and it is considered nil
only when both attributes are nil
.
With the first call (GiveMeANil(nilString)
) value
will be nil
while type
will be string*
, hence the interface{}
is not nil
.
With the second call, on the other hand, both value
and type
will be nil
, hence the interface{}
object is nil
.
You will think: "Hmm... ok, I understood, but... how do I check an interface{}
for nil
then?"
If you don't know the real underlying type or if you don't want to downcast, you need to use the reflection.
Here is the full working code:
package main
import (
"fmt"
"reflect"
)
func GiveMeANil(value interface{}) {
if value == nil || reflect.ValueOf(value).IsNil() {
fmt.Println("Thank you my friend! I really needed it!")
} else {
fmt.Println("Sorry mate, but I really need a nil...")
}
}
func main() {
var nilString *string = nil // explicitly assigning `nil` to make it clear
GiveMeANil(nilString)
GiveMeANil(nil)
}