Go-接口實現(xiàn)原理

Go-接口實現(xiàn)原理

接口的底層結(jié)構(gòu)

efaceiface

??efaceiface都是描述接口的數(shù)據(jù)結(jié)構(gòu),區(qū)別在于iface描述的接口包含方法、而eface描述的接口不包含方法

eface的數(shù)據(jù)結(jié)構(gòu)

type eface struct {
    _type *_type                    //實體類型
    data  unsafe.Pointer    //具體的值
}

eface主要包含實體類型_type指針和指向具體值的指針data,

  • _type描述了實體類型包括內(nèi)存大小、對齊方式等等,所有類型均可解釋為_type
  • data存儲了數(shù)據(jù)的指針,即使是對于數(shù)字、字符串這樣的字面值也是通過額外分配空間取指針的

iface的數(shù)據(jù)結(jié)構(gòu)

type iface struct {
    tab  *itab
    data unsafe.Pointer
}

type itab struct {
    inter *interfacetype
    _type *_type
    hash  uint32 // copy of _type.hash. Used for type switches.
    _     [4]byte
    fun   [1]uintptr // variable sized. fun[0]==0 means _type does not implement inter.
}

type interfacetype struct {
    typ     _type
    pkgpath name
    mhdr    []imethod
}
iface結(jié)構(gòu)圖.png

iface中存儲的是一個itab指針和一個指向數(shù)據(jù)的指針,itab中:

  • _type依舊描述了實體類型包括內(nèi)存大小、對齊方式等數(shù)據(jù)
  • inter則描述了接口自身的信息,其中的mhdr字段包含了接口所定義的方法
  • fun其實是一個動態(tài)數(shù)組,雖然聲明時是固定大小為1,但在使用時會直接通過fun指針獲取其中的數(shù)據(jù),類似于c語言中的不定長結(jié)構(gòu)體

值接收者和指針接受者

package main

type Person struct {
    age int
}
func (p Person) howOld() int {
    return p.age
}
func (p *Person) growUp() {
    p.age += 1
}

func  main() {
    p1 := Person{}
    p2 := &Person{}
    p1.howOld()
    p1.growUp()

    p2.howOld()
    p2.growUp()
}

howOld是值接收者、growUp是指針接者,對于普通的函數(shù)調(diào)用而言在使用者go內(nèi)部做了兼容可以互相調(diào)用

但是在接口中這是不兼容的,指針類型、值類型賦值給接口其生成的函數(shù)集是不一樣的

函數(shù)集

值類型 函數(shù)集
(T) (t T)
指針(*T) (t T)(t *T)

原因很簡單:對于有一些值是無法取到指針的,比如數(shù)字、字符串的字面值

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容