Go的interface源码在Golang源码的runtime
目录中。 Go在不一样版本之间的interface结构可能会有所不一样,可是,总体的结构是不会改变的,此文章用的Go版本是1.11。微信
Go的interface是由两种类型来实现的:iface
和eface
。 其中,iface
表示的是包含方法的interface,例如:数据结构
type Person interface {
Print()
}
复制代码
而eface
表明的是不包含方法的interface,即函数
type Person interface {}
复制代码
或者ui
var person interface{} = xxxx实体
复制代码
eface
eface
的具体结构是: spa
_type
,一个是数据信息。 其中,
_type
能够认为是Go语言中全部类型的公共描述,Go语言中几乎全部的数据结构均可以抽象成
_type
,是全部类型的表现,能够说是万能类型,
data
是指向具体数据的指针。
type
的具体代码为:3d
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赋值后的内部结构是怎样的呢? 能够先看段代码:code
import (
"fmt"
"strconv"
)
type Binary uint64
func main() {
b := Binary(200)
any := (interface{})(b)
fmt.Println(any)
}
复制代码
输出200,赋值后的结构图是这样的: orm
type
万能结构的方法,是运行时的
convT2E
方法,在
runtime
包中。 以上,是对于没有方法的接口说明。 对于包含方法的函数,用到的是另外的一种结构,叫
iface
iface
全部包含方法的接口,都会使用iface
结构。包含方法的接口就是一下这种最多见,最普通的接口:cdn
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
互联网技术窝
或者加微信共同探讨交流: