[Go疑难杂症]为什么nil不等于nil( 三 )

进行类型强转,就可以通过打断点的方式来查看了 。
func TestErr(t *testing.T) { txn, err := startTx() fmt.Println(reflect.TypeOf(err), reflect.ValueOf(err)) if err != nil {log.Fatalf("err starting tx: %v", err) } p := (*iface)(unsafe.Pointer(&err)) fmt.Println(p.data) if err = txn.doUpdate(); err != nil {fmt.Println(reflect.TypeOf(err), reflect.ValueOf(err))p := (*iface)(unsafe.Pointer(&err))fmt.Println(p.data)log.Fatalf("err updating: %v", err) } if err = txn.commit(); err != nil {log.Fatalf("err committing: %v", err) } fmt.Println("success!")}

[Go疑难杂症]为什么nil不等于nil

文章插图
补充说明一下 , 这里的inter.typ.kind 表示的是变量的基本类型,其值对应 runtime 包下的枚举 。
const ( kindBool = 1 + iota kindInt kindInt8 kindInt16 kindInt32 kindInt64 kindUint kindUint8 kindUint16 kindUint32 kindUint64 kindUintptr kindFloat32 kindFloat64 kindComplex64 kindComplex128 kindArray kindChan kindFunc kindInterface kindMap kindPtr kindSlice kindString kindStruct kindUnsafePointer kindDirectIface = 1 << 5 kindGCProg= 1 << 6 kindMask= (1 << 5) - 1)比如上图中所示的 kind = 20 对应的类型就是 kindInterface
总结
  1. 接口类型变量跟普通变量是有差异的,非空接口类型变量对应的底层结构是 iface ,空接口类型类型变量对应的底层结构是 eface
  2. iface 中有两个跟类型相关的字段,一个表示的是接口的类型 inter,一个表示的是变量实际类型 _type
  3. 只有当接口变量的 itab._type 与 data 都为 nil 时,也就是实际类型和值都未被赋值前 , 才真正等于 nil
到此,一个有趣的探索之旅就结束了 , 但长路漫漫,前方还有无数的问题等待我们去探索和发现 , 这便是学习的乐趣,希望能与君共勉 。

推荐阅读