<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
iface
和eface
都是 Go 中描述介面的底層結構體,區別在於iface
描述的介面包含方法,而eface
則是不包含任何方法的空介面:interface{}
。
從原始碼層面看一下:
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 }
iface
內部維護兩個指標,tab
指向一個itab
實體, 它表示介面的型別以及賦給這個介面的實體型別。data
則指向介面具體的值,一般而言是一個指向堆記憶體的指標。
再來仔細看一下 itab 結構體:_type 欄位描述了實體的型別,包括記憶體對齊方式,大小等;inter 欄位則描述了介面的型別。fun 欄位放置和介面方法對應的具體資料型別的方法地址,實現介面呼叫方法的動態分派,一般在每次給介面賦值發生轉換時會更新此表,或者直接拿快取的 itab。
這裡只會列出實體型別和介面相關的方法,實體型別的其他方法並不會出現在這裡。如果你學過 C++ 的話,這裡可以類比虛擬函式的概念。
另外,你可能會覺得奇怪,為什麼 fun 陣列的大小為 1,要是介面定義了多個方法可怎麼辦?實際上,這裡儲存的是第一個方法的函數指標,如果有更多的方法,在它之後的記憶體空間裡繼續儲存。從組合角度來看,通過增加地址就能獲取到這些函數指標,沒什麼影響。順便提一句,這些方法是按照函數名稱的字典序進行排列的。
再看一下
interfacetype
型別,它描述的是介面的型別:
type interfacetype struct { typ _type pkgpath name mhdr []imethod }
可以看到,它包裝了
_type
型別,_type
實際上是描述 Go 語言中各種資料型別的結構體。我們注意到,這裡還包含一個mhdr
欄位,表示介面所定義的函數列表,pkgpath
記錄定義了介面的包名。
這裡通過一張圖來看下
iface
結構體的全貌:
接著來看一下
eface
的原始碼:
type eface struct { _type *_type data unsafe.Pointer }
相比
iface
,eface
就比較簡單了。只維護了一個_type
欄位,表示空介面所承載的具體的實體型別。data
描述了具體的值。
我們來看個例子:
package main import "fmt" func main() { x := 200 var any interface{} = x fmt.Println(any) g := Gopher{"Go"} var c coder = g fmt.Println(c) } type coder interface { code() debug() } type Gopher struct { language string } func (p Gopher) code() { fmt.Printf("I am coding %s languagen", p.language) } func (p Gopher) debug() { fmt.Printf("I am debuging %s languagen", p.language) }
執行命令,列印出組合語言:
go tool compile -S ./src/main.go
可以看到,main 函數裡呼叫了兩個函數:
func convT2E64(t *_type, elem unsafe.Pointer) (e eface) func convT2I(tab *itab, elem unsafe.Pointer) (i iface)
上面兩個函數的引數和
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 }
Go 語言各種資料型別都是在
_type
欄位的基礎上,增加一些額外的欄位來進行管理的:
type arraytype struct { typ _type elem *_type slice *_type len uintptr } type chantype struct { typ _type elem *_type dir uintptr } type slicetype struct { typ _type elem *_type } type structtype struct { typ _type pkgPath name fields []structfield }
這些資料型別的結構體定義,是反射實現的基礎。
到此這篇關於GoLang之iface 和 eface 的區別是什麼的文章就介紹到這了,更多相關GoLang iface 和 eface區別內容請搜尋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