nil slice when passed as interface is not nil! Why

2019-02-06 20:36发布

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?

标签: go null
1条回答
三岁会撩人
2楼-- · 2019-02-06 21:36

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.

查看更多
登录 后发表回答