Go interface 底层的 itab 到底是什么

发布时间:2026/5/30 14:57:51

Go interface 底层的 itab 到底是什么 你已经知道typeAnimalinterface{Speak()string}typeDogstruct{}func(d Dog)Speak()string{return汪汪}这里Animal 接口 Dog 结构体 Speak 方法那么Go 到底是怎么知道vara AnimalDog{}里面的 Dog 实现了 Animal又是怎么找到a.Speak()应该调用哪个函数的答案就是itab一、先看这段代码typeAnimalinterface{Speak()string}typeDogstruct{}func(d Dog)Speak()string{return汪汪}funcmain(){vara Animal aDog{}fmt.Println(a.Speak())}输出汪汪二、问题来了变量a类型是Animal但是真正装进去的是Dog{}那么执行a.Speak()的时候Go 怎么知道应该去调用Dog.Speak()而不是Cat.Speak()呢三、interface 底层结构前面讲过interface 本质(Type, Value)例如vara AnimalDog{}底层大概是T Dog V Dog{}四、但仅仅有类型还不够因为Go 还需要知道这个类型实现了哪些接口方法例如Dog ↓ Speak() ↓ 对应哪个函数地址五、于是出现了 itabitab全称interface table翻译接口方法表六、itab 是干什么的一句话记录 某个具体类型 如何实现某个接口七、画图理解例如vara AnimalDog{}底层大概这样a │ ├── itab │ └── data八、datadata保存真正的数据也就是Dog{}九、itabitab保存接口信息 具体类型信息 方法地址十、对应到你的代码接口类型typeAnimalinterface{Speak()string}对应Animal具体类型typeDogstruct{}对应Dog方法实现func(d Dog)Speak()string对应Dog.Speak()十一、itab 里面存什么大概可以理解成itab ├── interface type ├── concrete type └── method table具体itab ├── Animal ├── Dog └── Dog.Speak()十二、画成表项目对应interface typeAnimalconcrete typeDogmethodDog.Speak十三、执行 a.Speak() 时发生什么代码a.Speak()Go先找到a.itab然后在里面找到Speak 对应的函数地址最终调用Dog.Speak()十四、整个过程a.Speak() ↓ 找到 itab ↓ 找到 Speak 函数地址 ↓ 执行 Dog.Speak() ↓ 返回 汪汪十五、为什么接口调用比普通调用慢一点普通调用dog.Speak()编译时就知道调用哪个函数接口调用a.Speak()需要先查 itab 再跳转函数所以会多一步。十六、再举一个例子typeCatstruct{}func(c Cat)Speak()string{return喵喵}此时vara AnimalCat{}底层变成itab ├── Animal ├── Cat └── Cat.Speak()十七、为什么不用提前写 implementsJavaclassDogimplementsAnimalGo不用。因为Go 编译器会自动检查Dog 有没有实现 Animal 的全部方法如果有自动生成Animal-Dog 的 itab十八、编译器什么时候创建 itab当你写vara AnimalDog{}时。编译器发现Dog 实现了 Animal于是创建Animal ↔ Dog对应的 itab。十九、为什么接口断言能成功例如vara AnimalDog{}执行dog:a.(Dog)Go会看itab 里的 concrete type发现Dog于是断言成功。二十、结合 interface (Type, Value) 再理解很多教程说interface (Type, Value)其实更准确应该理解成interface ├── itab └── data其中data保存真正的数据例如Dog{}itab保存Dog 的类型 Animal 的信息 Dog.Speak 的地址二十一、最终完整图重点var a Animal Dog{}底层a │ ├── itab │ ├── interface type : Animal │ ├── concrete type : Dog │ └── method table │ └── Speak → Dog.Speak │ └── data └── Dog{}二十二、最后一句总结必须记住itab 本质接口方法映射表作用记录 某个具体类型 如何实现某个接口在你的例子里Animal ← 接口类型 Dog ← 具体类型 Dog.Speak ← 方法实现Go 会生成itab ├── Animal ├── Dog └── Speak → Dog.Speak当执行a.Speak()时实际上就是通过 itab 找到 Dog.Speak() 再调用所以interface 能装不同类型 却还能正确调用对应方法核心秘密就是itab data

相关新闻