深入了解Go的interface{}底層原理實(shí)現(xiàn)
1. interface{}初探
Go是強(qiáng)類型語言,各個(gè)實(shí)例變量的類型信息正是存放在interface{}中的,Go中的反射也與其底層結(jié)構(gòu)有關(guān)。
iface
和 eface
都是 Go 中描述interface{}的底層結(jié)構(gòu)體,區(qū)別在于 iface
描述的接口包含方法,而 eface
則是不包含任何方法的空接口:interface{}
。
接下來,我們將詳細(xì)剖析iface
和 eface
的底層數(shù)據(jù)結(jié)構(gòu)。
2. eface
eface
比較簡單,只維護(hù)了 _type
字段,表示空接口所承載的具體的實(shí)體類型,以及data
描述了具體的值。
type eface struct { _type *_type data unsafe.Pointer }
data
字段是iface
和 eface
都有的結(jié)構(gòu),這個(gè)是一個(gè)內(nèi)存指針,指向interface{}實(shí)例對象信息的存儲地址,在這里,我們可以獲取對象的具體屬性的數(shù)值信息。
而interface{}的類型信息是存放在_type
結(jié)構(gòu)體中的,如下所示,在eface
中,直接存放了_type
的指針,iface
中多了一層封裝,本節(jié)我們主要針對eface
做梳理,所以介紹_type
結(jié)構(gòu)體。
type _type struct { // 類型大小 size uintptr ptrdata uintptr // 類型的 hash 值 hash uint32 // 類型的 flag,和反射相關(guān) tflag tflag // 內(nèi)存對齊相關(guān) align uint8 fieldalign uint8 // 類型的編號,有bool, slice, struct 等等等等 kind uint8 alg *typeAlg // gc 相關(guān) gcdata *byte str nameOff ptrToThis typeOff }
我們可以看到size
,ptrdata
等表示interface{}對象的類型信息,hash
是其對應(yīng)的哈希值,用于map等的哈希算法,tflag
與反射相關(guān),而align
與fieldalign
是用來內(nèi)存對齊的,這與Go底層的內(nèi)存管理機(jī)制有關(guān),Go的內(nèi)存管理機(jī)制類似于Linux中的伙伴系統(tǒng),是以固定大小的內(nèi)存塊進(jìn)行內(nèi)存分配的,與這個(gè)大小進(jìn)行對齊消除外碎片,提高內(nèi)存利用率。另外還有一些和gc相關(guān)的參數(shù),大家有一個(gè)初步的理解與認(rèn)識就可以了,如果想深入掌握可以專門學(xué)習(xí)和查看源碼。
3. iface
與eface
不同,iface
結(jié)構(gòu)體中要同時(shí)儲存方法信息,其數(shù)據(jù)結(jié)構(gòu)如下圖所示。正如前面所說的,itab
結(jié)構(gòu)體封裝了_type
結(jié)構(gòu)體,同樣利用_type
儲存類型信息,另外,其還有一些其他的屬性。hash
是對_type
結(jié)構(gòu)體中hash
的拷貝,提高類型斷言的效率。bad
與inhash
都是標(biāo)記位,提高gc以及其他活動(dòng)的效率。fun
指向方法信息的具體地址。
另外,interfacetype
,他描述的是接口靜態(tài)類型信息。
fun
字段放置和接口方法對應(yīng)的具體數(shù)據(jù)類型的方法地址,實(shí)現(xiàn)接口調(diào)用方法的動(dòng)態(tài)分派,一般在每次給接口賦值發(fā)生轉(zhuǎn)換時(shí)會(huì)更新此表,或者直接拿緩存的 itab。這里只會(huì)列出實(shí)體類型和接口相關(guān)的方法,實(shí)體類型的其他方法并不會(huì)出現(xiàn)在這里。如果你學(xué)過 C++ 的話,這里可以類比虛函數(shù)的概念,至于靜態(tài)函數(shù),并不存放在這里。
C++ 和 Go 在定義接口方式上的不同,也導(dǎo)致了底層實(shí)現(xiàn)上的不同。C++ 通過虛函數(shù)表來實(shí)現(xiàn)基類調(diào)用派生類的函數(shù);而 Go 通過 itab
中的 fun
字段來實(shí)現(xiàn)接口變量調(diào)用實(shí)體類型的函數(shù)。C++ 中的虛函數(shù)表是在編譯期生成的;而 Go 的 itab
中的 fun
字段是在運(yùn)行期間動(dòng)態(tài)生成的。原因在于,Go 中實(shí)體類型可能會(huì)無意中實(shí)現(xiàn) N 多接口,很多接口并不是本來需要的,所以不能為類型實(shí)現(xiàn)的所有接口都生成一個(gè) itab
, 這也是“非侵入式”帶來的影響;這在 C++ 中是不存在的,因?yàn)榕缮枰@示聲明它繼承自哪個(gè)基類。
type iface struct { tab *itab data unsafe.Pointer } type itab struct { inter *interfacetype _type *_type link *itab hash uint32 // copy of _type.hash. Used for type switches. bad bool // type does not implement interface inhash bool // has this itab been added to hash? unused [2]byte fun [1]uintptr // variable sized } type interfacetype struct { typ _type pkgpath name mhdr []imethod }
綜合上面的分析,我們可以梳理出,iface
對應(yīng)的幾個(gè)重要數(shù)據(jù)結(jié)構(gòu)的關(guān)系如下圖所示。
4. 接口轉(zhuǎn)化
通過前面提到的 iface
的源碼可以看到,實(shí)際上它包含接口的類型 interfacetype
和 實(shí)體類型的類型 _type
,這兩者都是 iface
的字段 itab
的成員。也就是說生成一個(gè) itab
同時(shí)需要接口的類型和實(shí)體的類型。
->itable
當(dāng)判定一種類型是否滿足某個(gè)接口時(shí),Go 使用類型的方法集和接口所需要的方法集進(jìn)行匹配,如果類型的方法集完全包含接口的方法集,則可認(rèn)為該類型實(shí)現(xiàn)了該接口。
例如某類型有 m
個(gè)方法,某接口有 n
個(gè)方法,則很容易知道這種判定的時(shí)間復(fù)雜度為 O(mn)
,Go 會(huì)對方法集的函數(shù)按照函數(shù)名的字典序進(jìn)行排序,所以實(shí)際的時(shí)間復(fù)雜度為 O(m+n)
。
Go的接口實(shí)現(xiàn)是非侵入式的,而是鴨子模式:如果某個(gè)東西長得像鴨子,像鴨子一樣游泳,像鴨子一樣嘎嘎叫,那它就可以被看成是一只鴨子。
因此,只要我們實(shí)現(xiàn)了接口對應(yīng)的方法,也就實(shí)現(xiàn)了對應(yīng)的接口,不需要單獨(dú)申明。
到此這篇關(guān)于深入了解Go的interface{}底層原理實(shí)現(xiàn)的文章就介紹到這了,更多相關(guān)Go interface{}底層原理內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Golang中時(shí)間格式化的實(shí)現(xiàn)詳解
這篇文章主要為大家詳細(xì)介紹了Go語言中進(jìn)行時(shí)間進(jìn)行格式化的相關(guān)知識,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起了解一下2023-09-09詳解Golang實(shí)現(xiàn)請求限流的幾種辦法
這篇文章主要介紹了詳解Golang實(shí)現(xiàn)請求限流的幾種辦法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-04-04淺析Go項(xiàng)目中的依賴包管理與Go?Module常規(guī)操作
這篇文章主要為大家詳細(xì)介紹了Go項(xiàng)目中的依賴包管理與Go?Module常規(guī)操作,文中的示例代碼講解詳細(xì),對我們深入了解Go語言有一定的幫助,需要的可以跟隨小編一起學(xué)習(xí)一下2023-10-10Go?io/fs.FileMode文件系統(tǒng)基本操作和權(quán)限管理深入理解
這篇文章主要為大家介紹了Go?io/fs.FileMode文件系統(tǒng)基本操作和權(quán)限管理深入理解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2024-01-01