Go语言interface底层实现
source link: https://studygolang.com/articles/20180?amp%3Butm_medium=referral
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
Go的interface源码在Golang源码的 runtime
目录中。
Go在不同版本之间的interface结构可能会有所不同,但是,整体的结构是不会改变的,此文章用的Go版本是1.11。
Go的interface是由两种类型来实现的: iface
和 eface
。
其中, iface
表示的是包含方法的interface,例如:
type Person interface { Print() }
而 eface
代表的是不包含方法的interface,即
type Person interface {}
或者
var person interface{} = xxxx实体
eface
eface
的具体结构是:
在这里插入图片描述
一共有两个属性构成,一个是类型信息 _type
,一个是数据信息。
其中, _type
可以认为是Go语言中所有类型的公共描述,Go语言中几乎所有的数据结构都可以抽象成 _type
,是所有类型的表现,可以说是万能类型,
data
是指向具体数据的指针。
type
的具体代码为:
type _type struct { size uintptr ptrdata uintptr // size of memory prefix holding all pointers hash uint32 tflag tflag align uint8 fieldalign uint8 kind uint8 alg *typeAlg // gcdata stores the GC type data for the garbage collector. // If the KindGCProg bit is set in kind, gcdata is a GC program. // Otherwise it is a ptrmask bitmap. See mbitmap.go for details. gcdata *byte str nameOff ptrToThis typeOff }
eface
的整体结构是:
在这里插入图片描述
对于没有方法的interface赋值后的内部结构是怎样的呢?
可以先看段代码:
import ( "fmt" "strconv" ) type Binary uint64 func main() { b := Binary(200) any := (interface{})(b) fmt.Println(any) }
输出200,赋值后的结构图是这样的:
在这里插入图片描述
对于将不同类型转化成 type
万能结构的方法,是运行时的 convT2E
方法,在 runtime
包中。
以上,是对于没有方法的接口说明。
对于包含方法的函数,用到的是另外的一种结构,叫iface
iface
所有包含方法的接口,都会使用 iface
结构。包含方法的接口就是一下这种最常见,最普通的接口:
type Person interface { Print() }
iface
的源代码是:
type iface struct { tab *itab data unsafe.Pointer }
iface
的具体结构是:
在这里插入图片描述
itab
是 iface
不同于 eface
比较关键的数据结构。其可包含两部分:一部分是确定唯一的包含方法的interface的具体结构类型,一部分是指向具体方法集的指针。
具体结构为:
在这里插入图片描述
itab
的源代码是:
type itab struct { inter *interfacetype //此属性用于定位到具体interface _type *_type //此属性用于定位到具体interface 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. }
属性 interfacetype
类似于 _type
,其作用就是interface的公共描述,类似的还有 maptype
、 arraytype
、 chantype
...其都是各个结构的公共描述,可以理解为一种外在的表现信息。 interfacetype
源码如下:
type interfacetype struct { typ _type pkgpath name mhdr []imethod } type imethod struct { name nameOff ityp typeOff }
iface
的整体结构为:
在这里插入图片描述
对于含有方法的interface赋值后的内部结构是怎样的呢?
一下代码运行后
package main import ( "fmt" "strconv" ) type Binary uint64 func (i Binary) String() string { return strconv.FormatUint(i.Get(), 10) } func (i Binary) Get() uint64 { return uint64(i) } func main() { b := Binary(200) any := fmt.Stringer(b) fmt.Println(any) }
首先,要知道代码运行结果为:200。
其次,了解到 fmt.Stringer
是一个包含 String
方法的接口。
type Stringer interface { String() string }
最后,赋值后接口 Stringer
的内部结构为:
在这里插入图片描述
对于将不同类型转化成itable中 type(Binary)
的方法,是运行时的 convT2I
方法,在 runtime
包中。
参考文献:
《Go in action》
https://research.swtch.com/interfaces
https://juejin.im/entry/5a7d08d3f265da4e865a6200 更多精彩内容,请关注我的微信公众号 互联网技术窝
或者加微信共同探讨交流:
image
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK