nil slice作为接口传递时不是零!为什么? (golang)

时间:2014-01-30 15:37:08

标签: go null

查看此游乐场: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)
}

为什么两个函数之间的输出差异?

2 个答案:

答案 0 :(得分:14)

不可否认,这有些怪癖,但有一个解释。

想象一个interface{}变量作为由两个字段组成的结构:一个是类型,另一个是数据。 ([]intnil)。实际上,它在Go运行时看起来就像那样。

struct Iface                                                                                                                   
{                                                                                                                              
    Itab*   tab;                                                                                                               
    void*   data;                                                                                                              
};   

当您将nil切片传递给yes时,只会传递nil作为值,因此您的比较会归结为nil == nil

同时,调用no会自动将您的变量换成interface{}类型,并且该调用会变成类似no(interface{[]int, nil})的内容。因此,no中的比较可以被视为interface{[]int, nil} == nil,在go中证明是错误的。

问题实际上已在the Go FAQ中解释。

答案 1 :(得分:0)

要添加到@justinas 的答案中,如果您需要比较inside 接口值{} 中的值,您可以使用 reflect.ValueOf.IsNil 方法报告 if value inside 接口{}为零。

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!
}