详解 Go Interface 的数据结构

date
Mar 9, 2025
tags
编程
Go
slug
go-interface-data-structure
status
Published
summary
理解 interface 底层数据结构
type
Post
非原创,主要是对这篇文章的整理和反思。
对于 Go 中的 interface 变量,其结构由两个字组成,第一个字指向 interface table ,简称 itable,itable 中存储类型和接口对应的方法(函数指针),第二个字用来指向数据(变量)。
一般的,假设有代码:
在 32 位机器上,则有结构:
图 1
图 1
注意这里的 (*MyType).String 为什么看起来接收器是指针呢?因为对于 b,其在调用 String 方法时本质是以下代码: b.tab->fun[0](b.data) 这里 b.data 是指针,所以尽管定义的值接收器,实际还是存储了引用接收器类型。(个人理解)

Go 对于 interface 结构的两种优化

  1. interface 为空,也就是 interface{} 的情况下,第一个字直接指向类型,不再指向 itable。
  1. 数据可以直接存储在第二个字内,不需要间接指向时,第二个字可以直接存储数据
举个例子:
在 32 位机器上,一个字 32 位,1 是 int32 型,可以直接存储,再加上 interface{},两种优化叠加,结构如下:
图 2
图 2

itable 什么时候计算

在赋值或转换语句时计算,也就是运行时计算,此时 go runtime 对照接口和实际类型实现的方法确保接口所有的方法都已经实现(否则会在编译时就报错了),然后构造 itable 将方法加入 itable。
不难想到对照两组方法需要 O(m * n) 的时间复杂度,对两者排序可以优化到 O(m + n) 。
如上图 1 所示,itable 靠 (interface type, variable type) 来标识,后续需要使用可以直接使用,无需重复计算。

© Aron Yang 2024 - 2025