在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***ce
和eface
的定義是如此的相似,以至於讓我們迫不及待的想去看看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
函式的引數就是空介面。
現在的問題就是乙個具體型別的值是如何轉換為iface
或eface
的,這其實是編譯器幫我們實現的,其中的字段也是由編譯器進行填充的。
反射與介面的合併
做整合對接的介面比較多樣。介面設計者經常是定義乙個入口,要求呼叫者傳入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...