Reputation: 5955
See this playground: http://play.golang.org/p/nWHmlw1W01
package main
import "fmt"
func main() {
var i []int = nil
yes(i) // output: true
no(i) // output: false
}
func yes(thing []int) {
fmt.Println(thing == nil)
}
func no(thing interface{}) {
fmt.Println(thing == nil)
}
Why the difference in output between the two functions?
Upvotes: 14
Views: 2847
Reputation: 361
To add to @justinas' answer, if you need to compare the value inside the interface{}
value, you can use reflect.ValueOf.IsNil()
method which would report if value inside the interface{}
is nil.
func main() {
var a []int = nil
var ai interface{} = a
r1 := a == nil // true
r2 := ai == nil // false, interface is not nil
vo := reflect.ValueOf(ai).IsNil() // true, value inside interface is nil!
}
Upvotes: 1
Reputation: 6857
Admittedly, it's somewhat of a quirk, but there's an explanation for it.
Imagine an interface{}
variable as a struct composed of two fields: one is the type and another is the data. ([]int
and nil
). Actually, it looks just like that in the Go runtime.
struct Iface
{
Itab* tab;
void* data;
};
When you pass your nil slice to yes
, only nil
is passed as the value, so your comparison boils down to nil == nil
.
Meanwhile, calling no
automatically wraps your variable in an interface{}
type and the call becomes something akin to no(interface{[]int, nil})
. So the comparison in no
could be seen as interface{[]int, nil} == nil
, which turns out to be false in go.
The issue is actually explained in the Go FAQ.
Upvotes: 18