直接回答:接口值是两个字宽的 fat pointer。非空接口用 iface{tab *itab, data unsafe.Pointer},空接口用 eface{_type, data}。itab 是「接口类型 × 具体类型」的组合产物,含接口类型、动态类型和方法表 fun [n]uintptr;data 指向实际值。接口变量 != nil 当且仅当 tab/_type 非空——这就是 nil *T 装进接口后 != nil 的根源。

动态派发:给接口赋值时,运行时在全局 itab 哈希表查找或构造对应 itab(有缓存,构建成本一次性)。调用接口方法编译为 itab.fun[i] 间接跳转:取方法表第 i 项地址,把 data 作为接收者传入。比直接调用多一次内存间接,且地址运行时才知、通常无法内联,热点路径有可测开销,但现代 CPU 分支预测下一般不是瓶颈。类型断言与 type switch 比较 itab 中的类型指针,O(1)。接口相等比较先比 tab 再比 data 指向的值,所以装着 slice 等不可比较类型的接口值用 == 会 panic。这套结构还解释了方法集规则:值接收者方法同时属于 T 与 *T,itab 按方法集生成。

追问方向:itab 缓存如何管理?泛型单态化能否替代接口派发?(约 580 字)