背景案例
日常开发中经常会遇到返回interface,而这里就会面临判空的问题。
func main() {
var x interface{}
IsNil("x", x)
var y *string = nil
IsNil("y", y)
var z = (interface{})(y)
IsNil("z", z)
}
func IsNil(paramName string, input interface{}) {
if input == nil {
fmt.Printf(" %s == nil \n", paramName)
return
}
fmt.Printf(" %s != nil \n", paramName)
}
输出结果
这里为什么转成interface{}后,变成!=nil了呢
interface 底层结构
go 中 interface底层实现分为两类,eface为 empty-face,指不包含方法的interface结构,而iface则反之包含方法
type iface struct {
tab *itab
data unsafe.Pointer
}
type eface struct {
_type *_type
data unsafe.Pointer
}
但不是管是eface还是iface,其中都有一个_type属性 和 data
type itab struct {
inter *interfacetype
_type *_type
hash uint32 // copy of _type.hash. Used for type switches.
_ [4]byte
fun [1]uintptr // variable sized. fun[0]==0 means _type does not implement inter.
}
nil的定义
// nil is a predeclared identifier representing the zero value for a
// pointer, channel, func, interface, map, or slice type.
var nil Type // Type must be a pointer, channel, func, interface, map, or slice type
对于interface而言,nil的含义为data为空且类型为空。这就很好解释了为什么interface判空不能直接通过==来判断。
func main() {
var x interface{}
fmt.Println(reflect.TypeOf(x))
IsNil("x", x)
var y *string = nil
fmt.Println(reflect.TypeOf(y))
IsNil("y", y)
var z = (interface{})(y)
fmt.Println(reflect.TypeOf(z))
IsNil("z", z)
}
输出结果
如何判断nil
func IsNil(input interface{}) bool {
if input == nil {
return true
}
if reflect.TypeOf(input).Kind() == reflect.Ptr && reflect.ValueOf(input).IsNil() {
return true
}
return false
}