Go-接口實現原理 Go-接口實現原理

Go-接口實現原理

接口的底層結構

efaceiface

  efaceiface都是描述接口的數據結構,區別在於iface描述的接口包含方法、而eface描述的接口不包含方法

eface的數據結構

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

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

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

iface的數據結構

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中存儲的是一個itab指針和一個指向數據的指針,itab中:

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

值接收者和指針接受者

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是指針接者,對於普通的函數調用而言在使用者go內部做了兼容可以互相調用

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

函數集

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

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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章