距离 Go1.18 正式发布泛型已经过去了 6 个版本,目前最新的版本是 Go1.24(2025.02 发布的)。但目前 Go 仍然不支持泛型方法。这是为什么呢,是缺陷吗,还是设计如此?
问题原因
结合 Go 泛型的提案《Type Parameters Proposal[1]》可以得知,这在现阶段是设计如此。也就是设计提案上就没有去支持泛型方法。

官方设计文档给出以下缘由说明:
在既有的泛型设计中,Go 不允许方法,声明该方法特有的类型参数。接收者可以有类型参数,但方法不能添加任何类型参数。难以实现的原因,官方给出了 4 个 package 互相引用的包来以此说明其问题点。
package1:
package p1
// 堆代码 duidaima.com
// S is a type with a parameterized method Identity.
type S struct{}
// Identity is a simple identity method that works for any type.
func (S) Identity[T any](v T "T any") T { return v }
package2:
package p2
// HasIdentity is an interface that matches any type with a
// parameterized Identity method.
type HasIdentity interface {
Identity[T any](T "T any") T
}
package3:
package p3
import "p2"
// CheckIdentity checks the Identity method if it exists.
// Note that although this function calls a parameterized method,
// this function is not itself parameterized.
func CheckIdentity(v interface{}) {
if vi, ok := v.(p2.HasIdentity); ok {
if got := vi.Identity[int](0 "int"); got != 0 {
panic(got)
}
}
}
package4:
package p4
import (
"p1"
"p3"
)
// CheckSIdentity passes an S value to CheckIdentity.
func CheckSIdentity() {
p3.CheckIdentity(p1.S{})
}
在这个示例中,我们有一个 p1.S 类型,它包含一个参数化方法,同时还有一个 p2.HasIdentity 类型,它同样包含一个参数化方法。
p1.S 实现了 p2.HasIdentity,因此 p3.CheckIdentity 函数可以使用 int 作为参数调用 vi.Identity。当 p4.CheckSIdentity 调用时,这实际上会触发 p1.S.Identity[int] 的调用。
但是,问题出现了:p3 包对 p1.S 类型一无所知,并且在程序的其他部分可能并没有调用 p1.S.Identity。因此按照现有的 Go 编译器的机机制是无法实例化 p1.S.Identity[int] 的,必须要在某个地方实例化过他才能做。
可能的方向
原提案作者 @Ian Lance Taylor 也思考了几种想象中的 Go 泛型方法。但都能找出比较大的缺陷。因此一直没有推进。

分别是:遍历调用链、JIT、改语法。
遍历调用链
可以在链接时(link time)实例化它,但在一般情况下,这需要链接器遍历整个程序的调用图,以确定可能传递给 CheckIdentity 的类型集合。但问题在于:即使完成了这样的遍历,在涉及类型反射(type reflection)时,仍然可能不够充分。因为反射可能会基于用户输入的字符串来查找方法,这意味着无法在编译或链接时完全确定所有可能的调用。
因此若要在链接时实例化所有参数化方法,就可能需要为每种可能的类型参数实例化所有参数化方法,而这显然是不可行的。
JIT
在运行时(run time)实例化,这通常意味着使用某种 JIT(即时编译)技术,或者通过某种基于反射的方式来执行。但问题在于:这两种方法的实现都非常复杂,并且在运行时的性能开销可能会很高。
改语法
可以选择让参数化方法根本不实现接口(interface)。但如果这样做,我们又必须重新思考方法(method)的意义。如果不考虑接口,任何参数化方法都可以简单地用一个参数化函数(generic function)来实现。
总结
截止目前而言,Go 泛型方法的支持还处于纠结的尴尬境地。Go 官方也承认该项特性看起来非常有用。实际在语言设计上,需要确定思路和实现方向,以此达到较好的性能和开销体验。
参考资料
[1]Type Parameters Proposal: https://go.googlesource.com/proposal/+/refs/heads/master/design/43651-type-parameters.md#No-parameterized-methods~~~~