interface底层使用2个struct表示:eface和iface , 位置 src/runtime/runtime2.go
image.pngimage.png
// 有方法的接口 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.
}
// runtime/type.go
// 非空接口类型,接口定义,包路径等。
type interfacetype struct {
typ _type
pkgpath name
mhdr []imethod // 接口方法声明列表,按字典序排序
}
// 接口的方法声明,一种函数声明的抽象
// 比如:func Print() error
type imethod struct {
name nameOff // 方法名
ityp typeOff // 描述方法参数返回值等细节
}
type nameOff int32
type typeOff int32
method 存的是func 的声明抽象,而 itab 中的 fun 字段才是存储 func 的真实切片。
// 没有方法的接口 eface 空接口定义
type eface struct {
_type *_type //类型信息
data unsafe.Pointer //数据信息,指向数据指针
}
type _type struct {
size uintptr
ptrdata uintptr // size of memory prefix holding all pointers
hash uint32
tflag tflag
align uint8
fieldAlign uint8
kind uint8
// function for comparing objects of this type
// (ptr to object A, ptr to object B) -> ==?
equal func(unsafe.Pointer, unsafe.Pointer) bool
// 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
}
没有方法的interface赋值后内部结构
import (
"fmt"
"strconv"
)
type Binary uint64
func main() {
b := Binary(200)
any := (interface{})(b)
fmt.Println(any)
}
输出200,赋值后的结构图是这样的
image.png
iface 非空接口
非空接口(iface)本身除了可以容纳满足其接口的对象之外,还需要保存其接口的方法,因此除了data字段,iface通过tab字段描述非空接口的细节,包括接口方法定义,接口方法实现地址,接口所指类型等。iface是非空接口的实现,而不是类型定义,iface的真正类型为interfacetype,其第一个字段仍然为描述其自身类型的_type字段。
image.png
含有方法的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)
}
赋值后接口Stringer的内部结构为
image.png
网友评论