Go什么情况nil != nil

上述代码执行结果竟然是:

interface 变量定义是一个 16 个字节的结构体,首 8 字节是类型字段,后 8 字节是数据指针。普通的 interface 是 iface 结构,interface{} 对应的是 eface 结构;
interface 变量新创建的时候是 nil ,则这 16 个字节是全 0 值;
interface 变量的 nil 判断,汇编逻辑是判断首 8 字节是否是 0 值;
非空接口interface具体类型:
type iface struct {
tab *itab // 接口本身信息接口方法,并且存储具体类型所实现的信息
data unsafe.Pointer // 内存地址
}
空接口具体类型:
type eface struct {
_type *_type // 具体类型信息
data unsafe.Pointer // 内存地址
}
type itab struct {
inter *interfacetype // 包含接口类型typ,包名,方法切面的结构体指针
_type *_type // 下面说
// 当前类型的哈希值,runtime基于这个值构建类型映射表,加速类型比较和查找
hash uint32 // copy of _type.hash. Used for type switches.
_ [4]byte // 4字节用于内存对齐
fun [1]uintptr // variable sized. fun[0]==0 means _type does not implement inter. // 接口方法中的一个存储在这里,如果fun[0]是0的话默认不是某个结构体的接口
}
type _type struct {
size uintptr // 表示此类型的数据需要占用多少字节的存储空间
ptrdata uintptr // size of memory prefix holding all pointers ptrdata 表示数据的前多少字节包含指针,用来在应用写屏障时优化范围大小
hash uint32 // 当前类型的哈希值,runtime基于这个值构建类型映射表,加速类型比较和查找
tflag tflag // 额外的类型标识,目前由4个独立的二进制位组合而成。
align uint8 // 表示当前类型变量的对齐边界
fieldAlign uint8 // 表示当前类型的 struct 字段的对齐边界
kind uint8 // 表示当前类型所属的分类,目前 Go语言的 reflect 包中定义了 40 种有效分类
equal func(unsafe.Pointer, unsafe.Pointer) bool // 用来比较两个当前类型的变量是否相等
gcdata *byte // 和垃圾回收相关,GC 扫描和写屏障用来追踪指针
str nameOff // 偏移,通过 str 可以找到当前类型的名称等文本信息
ptrToThis typeOff // 偏移,假设当前类型为 T,通过它可以找到类型 * T的类型元数据
}
type interfacetype struct {
typ _type // 接口类型typ
pkgpath name // 包路径名pkgpath
mhdr []imethod // 存储接口方法集的切片mhdr
}
我们进行空接口和非空接口类型变量赋值的时候,返回如果是nil的接口体指针,就会导致,*itab 或者 *_type不是nil,是有类型指针的,这块大家需要注意!