go反射與介面

2021-10-20 09:08:08 字數 1565 閱讀 5961

在go反射的秘密一文中,我從源**的角度分析了go反射的相關細節,但是在那篇文章中,還是留下了兩個疑問:

為什麼typeof函式的實現是直接強制型別轉換?

乙個具體型別的變數是如何轉成inte***ce的?

由於當時的我年少無知,沒能解答出這兩個問題。時過境遷,再次讀書的時候偶然明悟,遂作此文以解惑。

讓我們再次回顧一下typeof函式的原始碼:

/*--type.go--*/

func

typeof

(i inte***ce

) type

/* ... ... */

type emptyinte***ce struct

其實從原始碼中我們也能大概推測是事情的原因,那就是inte***ce型別和emptyinte***ce型別必然有著相同的資料結構!只是當時沒能想到,也就失去了求證的機會。

在go原始碼runtime包的runtime2.go中,有如下**:

// 非空介面型別

type iface struct

// 空介面型別

type eface struct

可以看到emptyinte***ceeface的定義是如此的相似,以至於讓我們迫不及待的想去看看rtype_type的定義是否也相同。

// rtype is the common implementation of most values.

// it is embedded in other struct types.

//// rtype must be kept in sync with ../runtime/type.go:/^type._type.

type rtype struct

// needs to be in sync with ../cmd/link/internal/ld/decodesym.go:/^func.commonsize,

// ../cmd/compile/internal/gc/reflect.go:/^func.dcommontype and

// ../reflect/type.go:/^type.rtype.

// ../internal/reflectlite/type.go:/^type.rtype.

type _type struct

驚喜單不意外的是,它們兩的確是一模一樣,甚至注釋中還貼心的寫著它們必須保持同步。至於typeof函式直接強轉為emptyinte***ce型別,那是因為typeof函式的引數就是空介面。

現在的問題就是乙個具體型別的值是如何轉換為ifaceeface的,這其實是編譯器幫我們實現的,其中的字段也是由編譯器進行填充的。

反射與介面的合併

做整合對接的介面比較多樣。介面設計者經常是定義乙個入口,要求呼叫者傳入actionname來進行導向。比如actionname為method1,便呼叫method1方法,並給出相應的返回資訊。我們自然可以寫死,去switch方法名,然後寫呼叫方法,但這種方式非常冗餘,且後續你得一直維護。這裡介紹反射...

go 反射應用

直接上 package main import fmt reflect type envkey struct func main 反射 s reflect.valueof t elem typeoft s.type 迴圈遍歷結構體,獲取各個元素的型別,值 for i 0 i s.numfield i...

Go反射程式設計

reflect.typeof vs.reflect.valueof func checktype v inte ce func testbasictype t testing.t 利用反射編寫靈活的 type employee struct func e employee updateage new...