<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
Go是強型別語言,各個範例變數的型別資訊正是存放在interface{}中的,Go中的反射也與其底層結構有關。
iface
和 eface
都是 Go 中描述interface{}的底層結構體,區別在於 iface
描述的介面包含方法,而 eface
則是不包含任何方法的空介面:interface{}
。
接下來,我們將詳細剖析iface
和 eface
的底層資料結構。
eface
比較簡單,只維護了 _type
欄位,表示空介面所承載的具體的實體型別,以及data
描述了具體的值。
type eface struct { _type *_type data unsafe.Pointer }
data
欄位是iface
和 eface
都有的結構,這個是一個記憶體指標,指向interface{}範例物件資訊的儲存地址,在這裡,我們可以獲取物件的具體屬性的數值資訊。
而interface{}的型別資訊是存放在_type
結構體中的,如下所示,在eface
中,直接存放了_type
的指標,iface
中多了一層封裝,本節我們主要針對eface
做梳理,所以介紹_type
結構體。
type _type struct { // 型別大小 size uintptr ptrdata uintptr // 型別的 hash 值 hash uint32 // 型別的 flag,和反射相關 tflag tflag // 記憶體對齊相關 align uint8 fieldalign uint8 // 型別的編號,有bool, slice, struct 等等等等 kind uint8 alg *typeAlg // gc 相關 gcdata *byte str nameOff ptrToThis typeOff }
我們可以看到size
,ptrdata
等表示interface{}物件的型別資訊,hash
是其對應的雜湊值,用於map等的雜湊演演算法,tflag
與反射相關,而align
與fieldalign
是用來記憶體對齊的,這與Go底層的記憶體管理機制有關,Go的記憶體管理機制類似於Linux中的夥伴系統,是以固定大小的記憶體塊進行記憶體分配的,與這個大小進行對齊消除外碎片,提高記憶體利用率。另外還有一些和gc相關的引數,大家有一個初步的理解與認識就可以了,如果想深入掌握可以專門學習和檢視原始碼。
與eface
不同,iface
結構體中要同時儲存方法資訊,其資料結構如下圖所示。正如前面所說的,itab
結構體封裝了_type
結構體,同樣利用_type
儲存型別資訊,另外,其還有一些其他的屬性。hash
是對_type
結構體中hash
的拷貝,提高型別斷言的效率。bad
與inhash
都是標記位,提高gc以及其他活動的效率。fun
指向方法資訊的具體地址。
另外,interfacetype
,他描述的是介面靜態型別資訊。
fun
欄位放置和介面方法對應的具體資料型別的方法地址,實現介面呼叫方法的動態分派,一般在每次給介面賦值發生轉換時會更新此表,或者直接拿快取的 itab。這裡只會列出實體型別和介面相關的方法,實體型別的其他方法並不會出現在這裡。如果你學過 C++ 的話,這裡可以類比虛擬函式的概念,至於靜態函數,並不存放在這裡。
C++ 和 Go 在定義介面方式上的不同,也導致了底層實現上的不同。C++ 通過虛擬函式表來實現基礎類別呼叫派生類的函數;而 Go 通過 itab
中的 fun
欄位來實現介面變數呼叫實體型別的函數。C++ 中的虛擬函式表是在編譯期生成的;而 Go 的 itab
中的 fun
欄位是在執行期間動態生成的。原因在於,Go 中實體型別可能會無意中實現 N 多介面,很多介面並不是本來需要的,所以不能為型別實現的所有介面都生成一個 itab
, 這也是“非侵入式”帶來的影響;這在 C++ 中是不存在的,因為派生需要顯示宣告它繼承自哪個基礎類別。
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
對應的幾個重要資料結構的關係如下圖所示。
通過前面提到的 iface
的原始碼可以看到,實際上它包含介面的型別 interfacetype
和 實體型別的型別 _type
,這兩者都是 iface
的欄位 itab
的成員。也就是說生成一個 itab
同時需要介面的型別和實體的型別。
->itable
當判定一種型別是否滿足某個介面時,Go 使用型別的方法集和介面所需要的方法集進行匹配,如果型別的方法集完全包含介面的方法集,則可認為該型別實現了該介面。
例如某型別有 m
個方法,某介面有 n
個方法,則很容易知道這種判定的時間複雜度為 O(mn)
,Go 會對方法集的函數按照函數名的字典序進行排序,所以實際的時間複雜度為 O(m+n)
。
Go的介面實現是非侵入式的,而是鴨子模式:如果某個東西長得像鴨子,像鴨子一樣游泳,像鴨子一樣嘎嘎叫,那它就可以被看成是一隻鴨子。
因此,只要我們實現了介面對應的方法,也就實現了對應的介面,不需要單獨申明。
到此這篇關於深入瞭解Go的interface{}底層原理實現的文章就介紹到這了,更多相關Go interface{}底層原理內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45