Go interface 底层的 itab 到底是什么

你已经知道:

go 复制代码
type Animal interface {
    Speak() string
}

type Dog struct{}

func (d Dog) Speak() string {
    return "汪汪"
}

这里:

txt 复制代码
Animal = 接口
Dog = 结构体
Speak = 方法

那么:

Go 到底是怎么知道:

go 复制代码
var a Animal = Dog{}

里面的 Dog 实现了 Animal?

又是怎么找到:

go 复制代码
a.Speak()

应该调用哪个函数的?

答案:

就是:

txt 复制代码
itab

一、先看这段代码

go 复制代码
type Animal interface {
	Speak() string
}

type Dog struct{}

func (d Dog) Speak() string {
	return "汪汪"
}

func main() {

	var a Animal

	a = Dog{}

	fmt.Println(a.Speak())
}

输出:

txt 复制代码
汪汪

二、问题来了

变量:

go 复制代码
a

类型是:

go 复制代码
Animal

但是:

真正装进去的是:

go 复制代码
Dog{}

那么:

执行:

go 复制代码
a.Speak()

的时候:

Go 怎么知道:

应该去调用:

go 复制代码
Dog.Speak()

而不是:

go 复制代码
Cat.Speak()

呢?


三、interface 底层结构

前面讲过:

interface 本质:

txt 复制代码
(Type, Value)

例如:

go 复制代码
var a Animal = Dog{}

底层:

大概是:

txt 复制代码
T = Dog
V = Dog{}

四、但仅仅有类型还不够

因为:

Go 还需要知道:

txt 复制代码
这个类型实现了哪些接口方法

例如:

txt 复制代码
Dog
↓
Speak()
↓
对应哪个函数地址

五、于是出现了 itab

itab:

全称:

txt 复制代码
interface table

翻译:

txt 复制代码
接口方法表

六、itab 是干什么的

一句话:

txt 复制代码
记录
某个具体类型
如何实现某个接口

七、画图理解

例如:

go 复制代码
var a Animal = Dog{}

底层:

大概这样:

txt 复制代码
a
│
├── itab
│
└── data

八、data

data:

保存:

txt 复制代码
真正的数据

也就是:

txt 复制代码
Dog{}

九、itab

itab:

保存:

txt 复制代码
接口信息
+
具体类型信息
+
方法地址

十、对应到你的代码


接口类型

go 复制代码
type Animal interface {
    Speak() string
}

对应:

txt 复制代码
Animal

具体类型

go 复制代码
type Dog struct{}

对应:

txt 复制代码
Dog

方法实现

go 复制代码
func (d Dog) Speak() string

对应:

txt 复制代码
Dog.Speak()

十一、itab 里面存什么

大概可以理解成:

txt 复制代码
itab
├── interface type
├── concrete type
└── method table

具体:

txt 复制代码
itab
├── Animal
├── Dog
└── Dog.Speak()

十二、画成表

项目 对应
interface type Animal
concrete type Dog
method Dog.Speak

十三、执行 a.Speak() 时发生什么

代码:

go 复制代码
a.Speak()

Go:

先找到:

txt 复制代码
a.itab

然后:

在里面找到:

txt 复制代码
Speak 对应的函数地址

最终调用:

go 复制代码
Dog.Speak()

十四、整个过程

txt 复制代码
a.Speak()
↓
找到 itab
↓
找到 Speak 函数地址
↓
执行 Dog.Speak()
↓
返回 汪汪

十五、为什么接口调用比普通调用慢一点

普通调用:

go 复制代码
dog.Speak()

编译时:

就知道:

txt 复制代码
调用哪个函数

接口调用:

go 复制代码
a.Speak()

需要:

txt 复制代码
先查 itab
再跳转函数

所以:

会多一步。


十六、再举一个例子

go 复制代码
type Cat struct{}

func (c Cat) Speak() string {
	return "喵喵"
}

此时:

go 复制代码
var a Animal = Cat{}

底层:

变成:

txt 复制代码
itab
├── Animal
├── Cat
└── Cat.Speak()

十七、为什么不用提前写 implements

Java:

java 复制代码
class Dog implements Animal

Go:

不用。

因为:

Go 编译器:

会自动检查:

txt 复制代码
Dog 有没有实现 Animal 的全部方法

如果有:

自动生成:

txt 复制代码
Animal-Dog 的 itab

十八、编译器什么时候创建 itab

当你写:

go 复制代码
var a Animal = Dog{}

时。


编译器发现:

txt 复制代码
Dog 实现了 Animal

于是:

创建:

txt 复制代码
Animal ↔ Dog

对应的 itab。


十九、为什么接口断言能成功

例如:

go 复制代码
var a Animal = Dog{}

执行:

go 复制代码
dog := a.(Dog)

Go:

会看:

txt 复制代码
itab 里的 concrete type

发现:

txt 复制代码
Dog

于是:

断言成功。


二十、结合 interface = (Type, Value) 再理解

很多教程说:

txt 复制代码
interface = (Type, Value)

其实:

更准确:

应该理解成:

txt 复制代码
interface
├── itab
└── data

其中:


data

保存:

txt 复制代码
真正的数据

例如:

txt 复制代码
Dog{}

itab

保存:

txt 复制代码
Dog 的类型
Animal 的信息
Dog.Speak 的地址

二十一、最终完整图(重点)

txt 复制代码
var a Animal = Dog{}

底层:

txt 复制代码
a
│
├── itab
│   ├── interface type : Animal
│   ├── concrete type  : Dog
│   └── method table
│       └── Speak → Dog.Speak
│
└── data
    └── Dog{}

二十二、最后一句总结(必须记住)

itab 本质:

txt 复制代码
接口方法映射表

作用:

txt 复制代码
记录
某个具体类型
如何实现某个接口

在你的例子里:

txt 复制代码
Animal  ← 接口类型
Dog     ← 具体类型
Dog.Speak ← 方法实现

Go 会生成:

txt 复制代码
itab
├── Animal
├── Dog
└── Speak → Dog.Speak

当执行:

go 复制代码
a.Speak()

时:

实际上:

就是:

txt 复制代码
通过 itab
找到 Dog.Speak()
再调用

所以:

txt 复制代码
interface 能装不同类型
却还能正确调用对应方法

核心秘密:

就是:

txt 复制代码
itab + data
相关推荐
就叫_这个吧2 小时前
Java递归方法实现面包屑导航
java·开发语言
fīɡЙtīиɡ ℡3 小时前
AI 应用系统设计
java·开发语言·人工智能
AI绘画哇哒哒3 小时前
【建议收藏!】35岁后端血泪忠告,这3类人别硬转Agent(过来人亲述)
java·人工智能·后端·ai·程序员·大模型·agent
聪明蛋子哟4 小时前
Stagehand v3多语言SDK:Python/Go/Rust/Java下的浏览器自动化统一方案
python·golang·rust
唐青枫4 小时前
一个值多种形态:Zig union、Tagged Union 与内存布局实战
后端
今天AI了吗4 小时前
Python 基础语法(一):常量、变量、输入输出与运算符
开发语言·数据库·人工智能·python·sql·深度学习·机器学习
卷无止境4 小时前
Windows 上丝滑开发 Python,并稳定构建 Docker 镜像
后端·python·docker
Nturmoils4 小时前
备份完不算完,先还原到临时库验一遍
后端
TELL5215 小时前
selenium webdriver 第二次初始化的异常
开发语言·python
Csvn5 小时前
📊 SQL 入门 Day 22:视图与物化视图
后端·sql