[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
到此,一個有趣的探索之旅就結束了 , 但長路漫漫,前方還有無數的問題等待我們去探索和發現 , 這便是學習的樂趣,希望能與君共勉 。

推薦閱讀