go泛型在编译期单态化,无运行时实例化;类型参数需显式指定或由实参唯一推导;操作t需对应约束(如comparable、ordered或接口),否则编译错误。

Filter[string] 和 Filter[int],编译器会生成两份完全独立的机器码,就像你手动写了两个不同函数一样。
这不是模拟多态,而是真·编译期特化。理解这点,才能避开绝大多数坑。
泛型函数调用时类型参数怎么填?
两种方式:显式指定 or 编译器推导。
- 显式指定最稳妥,尤其当参数类型模糊时:
Map[int, string](nums, func(x int) string { return strconv.Itoa(x) }) - 编译器推导依赖所有实参能唯一确定类型参数。比如
Swap(a, b)中a和b都是*string,那T就是string;但如果传的是nil或 interface{} 值,推导就会失败,报错类似cannot infer T - 混合使用要小心:像
func F[T any, U comparable](x T, y U),如果只传一个参数,T可能推导出,但U没有实参可参考,就必须显式写成F[string, int]("hi", 42)
为什么 var x T 在泛型函数里不能直接用?
因为 T 是类型参数,不是具体类型,var x T 是合法的,但如果你紧接着想对 x 做操作(比如 x == y、len(x)、x.String()),就可能报错——除非你加了对应约束。
-
T any允许声明变量、赋值、传参,但禁止任何需要底层结构的操作 - 要比较相等?得用
T comparable - 要排序或比较大小?得用
T constraints.Ordered(需导入golang.org/x/exp/constraints) - 要调用方法?得定义接口约束,比如
type Stringer interface { String() string },再写T Stringer
泛型结构体如何“实例化”?
不是 new 出来,是**字面量构造或工厂函数返回**。
- 直接字面量:
stack := Stack[int]{items: []int{1, 2, 3}} - 用泛型构造函数更安全:
func NewStack[T any]() *Stack[T] { return &Stack[T]{items: make([]T, 0)} },调用st := NewStack[string]() - 别写
var s Stack[T]然后试图用——T在函数作用域里没绑定具体类型,这行不通;必须在类型定义上下文(如接收者func (s *Stack[T]) Push(v T))或调用点(如NewStack[string]())中明确 - 嵌套泛型要注意:像
Map[K comparable, V any],K必须支持 map key 要求,V则无限制;但如果你写成Map[string, []int],没问题;写成Map[[]int, string]就编译失败——因为切片不可比较
T any 看似自由,但一旦你用了 == 或 sort.Slice,它立刻变成编译错误。不是泛型“不支持”,是你没告诉编译器“这个 T 允许被比较”。golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











