可以这样理解,在实际使用的时候遇到interface类型需要判断是否为nil的时候需要格外留意,下面这种情况我们通常希望判断出err是为nil的,但直接判断下面这个err时,其实它是不等于nil的
func read() error {
var err *ReadErr
return err
}
err := read()
这种场景不仅会出现在err的判断上,一些其他函数或者方法返回的interface类型的数据我们也需要判断它实际上指向的底层数据是不是nil,这时候我们可以通过下面的方式进行判断:
func IsNil(i interface{}) bool {
if i == nil {
return true
}
vi := reflect.ValueOf(i)
return vi.IsNil()
}
上面的err经过上面的方式判断后IsNil(err)得到的就是true,上面是通过反射获取到err指向的值为nil。
还有一种情况也是需要格外留意的,当一个值为nil的数据类型作为interface进行传参时,经过参数转化成interface类型后,其值可能不为nil了,比如下面这个例子
func main(){
var s []string
fmt.Println("s==nil", s == nil)
NilParamToInterface(s)
}
func NilParamToInterface(i interface{}) {
fmt.Println("NilParamToInterface", i == nil)
}
上面的程序输出结果为:
s==nil true
NilParamToInterface false
变量s没有初始化,对它进行判断是否为nil毋容置疑是true的,但是它作为函数参数转成interface传入函数时,在函数中再次判断,其值就不为nil了,所以对于interface类型它需要记录原类型的类型信息,使得其值不为nil。如果需要判断它执行的底层数据的值是否为nil还是得通过反射来判断,如果使用上面的IsNil(s)函数判断s的值是否为nil,则返回的结果就是true了。