1 概述
1.1 结构体指针和nil比较
结构体指针能和nil直接用 “==” 和 “!=” 和nil进行比较。
1.2 接口和nil比较
接口类型的数据不能简单地使用"==" 和 “!=” 和nil进行比较。
当接口变量只声明不做初始化,或者直接赋值为nil时,此时 [ if 接口变量 == nil ] 为真。
接口变量被赋予动态值的时候,存储的是包含了这个动态值的副本的一个结构更加复杂的值,此时 [ if 接口变量 == nil ] 一定为假。
当给一个接口变量赋值的时候,该变量的动态类型会与它的动态值一起被存储在一个专用的数据结构中,这个专用的数据结构叫做iface,iface的实例会包含两个指针,一个是指向[ 类型信息 ]的指针,另一个是指向[ 动态值 ]的指针。[ 类型信息 ]是由另一个专用数据结构的实例承载的,其中包含了动态值的类型,以及使它实现了接口的方法和调用它们的途径。
2 例子
package main
import (
"fmt"
)
type MyImplement struct{}
// 结构体MyImplement实现fmt.Stringer的String方法
func (m *MyImplement) String() string {
return "hi"
}
func GetStringer() fmt.Stringer {
var s *MyImplement
// 此时 s == nil 为真,但是作为接口返回给上层时,上层用if语句判断 fmt.Stringer == nil 为假
// 因为接口变量在此处发生了初始化,被赋值为结构体指针
return s
}
func main() {
var result fmt.Stringer
if result == nil {
fmt.Println("result == nil")
}
result = GetStringer()
if result == nil {
fmt.Println("GetStringer() == nil")
} else {
fmt.Println("GetStringer() != nil")
}
}
3 小结
判断接口变量时,建议不要简单地使用 == 和 != 来判断,使用reflect.ValueOf(xxx).IsNil()等反射方式来判断。