接口
接口的底层结构
runtime\runtime2.go.iface
是带方法签名的接口在运行时的具体结构
// 是带方法签名的接口在运行时的具体结构
type iface struct {
// 存储接口的类型、动态数据类型、动态数据类型的函数指针 《重点》
tab *itab
// 存储了接口中动态类型的函数指针
data unsafe.Pointer
}
接口底层结构的完整图像
type itab struct {
inter *interfacetype // 代表接口本身的类型,是对_type的简单包装
_type *_type // 代表接口存储的动态类型,Go语言的各种数据类型 都是在_type字段的基础上通过增加额外字段来管理的
hash uint32 // copy of _type.hash. Used for type switches.是接口动态类型的唯一标识
_ [4]byte // 用于内存对齐
// fun 代表接口动态类型中的函数指针列表,用于运行时接口调用动态函数。虽然在运行时只定义了大小为1的数组[1] uintptr,
// 但是其存储的是函数首地址的指针。当由多个函数时,其指针会依次在下方进行存储。在运行时,可以通过首地址+偏移找到任意的函数指针
fun [1]uintptr // variable sized. fun[0]==0 means _type does not implement inter.
}
以下代码段
接口s的底层结构
接口内存逃逸分析
很容易想到,data字段存储了接口中具体值的指针,这是由于存 储的数据可能很大也可能很小,难以预料。但这也表明,存储在接口 中的值必须能够获取其地址,所以平时分配在栈中的值一旦赋值给接 口后,会发生内存逃逸,在堆区为其开辟内存。我们可以以一段简单 的程序part3_escape.go为例验证内存溢出问题。
参考书籍:《Go语言底层原理剖析》