接口interface

发布时间 2023-10-15 17:49:56作者: 小桔子1024

1. 接口的底层结构体

iface和eface,区别在于iface描述的接口包含方法,而eface则是不包含任何方法的空接口:interface{}

1.1 iface源码

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

type itab struct {
	inter  *interfacetype
	_type  *_type
	link   *itab
	hash   uint32 // copy of _type.hash. Used for type switches.
	bad    bool   // type does not implement interface
	inhash bool   // has this itab been added to hash?
	unused [2]byte
	fun    [1]uintptr // variable sized
}

说明:iface内部维护两个指针,tab指向一个itab实体, 表示接口的类型以及赋给这个接口的实体类型。data指向接口具体的值,一般而言是一个指向堆内存的指针

interfacetype类型:

type interfacetype struct {
    typ     _type
    pkgpath name
    mhdr    []imethod
}

iface结构体图示:

1.2 eface的源码

type eface struct {
    _type *_type // 动态类型
    data  unsafe.Pointer
}

说明:eface维护了一个 _type 字段,表示空接口所承载的具体的实体类型,data描述了具体的值

举例:

f, _ := os.Open("text.txt") // f => *os.File
var i1 interface{}
i1 = f

说明:eface的data字段的值就是f,_type就是*os.File类型的元数据

验证:

func TestInterface(t *testing.T) {
	f, _ := os.Open("text.txt")
	fmt.Printf("f pointer:%p\n", f)
	fmt.Println("==========")

	var i1 interface{}
	i1 = f
	ptr2 := unsafe.Pointer(&i1)
	opt2 := (*[2]unsafe.Pointer)(ptr2)
	fmt.Println("interface: ", opt2[0], opt2[1])
}

输出:

f pointer:0xc00000e038
==========
interface:  0x11091e0 0xc00000e038

说明: i1的interface{}变量的data值与f的地址是一样的。