Go中的泛型与any、interface有什么区别?
具体案例可看泛型 | Golang 中文学习文档!
any=interface{}Go 1.18 以后,any就是空接口的别名,两者完全一样!- 空接口 /any:能装所有类型,但会丢失类型信息
- 泛型
[T int|string]:类型模板,保留类型信息,编译时检查
any / interface{} = 黑色垃圾袋
啥都能装苹果、香蕉、石头、玩具,装进去后,你不知道里面装的是什么,拿出来必须摸一摸、猜一猜(类型断言),猜错了直接崩溃(panic)。
泛型 [T int|string] = 定制水果盒
这个盒子只能装苹果 / 香蕉,装的时候就知道是什么,拿出来直接吃,不用猜,绝对不会装错,编译时就帮你检查好了
什么时候用哪个?
✅ 用 any /interface {} 的场景
你只需要存储 / 传递数据,完全不关心它是什么类型,也不操作它
- 打印日志
fmt.Println(任意值) - 存任意类型的 map
map[string]any - 不需要解析的通用消息(比如简单透传)
- 你真的不知道、也不需要知道传进来的是什么
// 例子:打印任何东西(用any最合适)
func PrintAny(v any) {
fmt.Println(v)
}
✅ 用 泛型 的场景
你要对数据做操作(加减、比较、遍历、修改),又想复用代码,还想安全
- 通用切片去重
- 通用栈 / 队列
- 通用比较大小
- 通用数据处理工具
- 你希望一套代码支持多种类型,但不想丢失类型安全
// 泛型:加法函数,支持 int / float64
func Add[T int | float64](a T, b T) T {
return a + b
}
// 直接用,不用断言!
Add(1, 2) // int
Add(1.5, 2.3) // float64
用 any 实现加法(麻烦、不安全)
func AddAny(a any, b any) (any, error) {
// 必须断言!!!
switch a.(type) {
case int:
return a.(int) + b.(int), nil
case float64:
return a.(float64) + b.(float64), nil
default:
return nil, errors.New("不支持的类型")
}
}
// 用起来超级麻烦
res, _ := AddAny(1, 2)
fmt.Println(res) // 还是any类型,不能直接计算