preface

前一段时间golang的泛型再次被提及, 看了相关的proposal之后, 一直没空写, 最近终于得空, 写一波

特点

泛型 基于 type parameter 实现的, type parameter 通常用 [] 圈起来, 如下使用:

func F[T any] (p T) { .... }   // T 就是 F 的 type parameter
type M[T any] []T     // type parameter list 的定义
func F[T Contraint](p T) { .... } // 具有约束的泛型

与之相对的是, 常规的参数是 non-type parameter, 两者最显著的区别就是 [].

除了 type parameter, 频繁的词是 type argument, 是运行泛型代码的时候的入参, 会替换掉 type parameter.

约束可以理解成 对 泛型的行为定义, 但是相比于java, 缺乏了 extend 和 super, 通常用 interface 约束泛型, 比如:

// Stringify calls the String method on each element of s,
// and returns the results.
func Stringify[T Stringer](s []T) (ret []string) {
	for _, v := range s {
		ret = append(ret, v.String())
	}
	return ret
}

这里用 Stringer 约束了 T 的行为, 需要注意的是, T 的参数只能使用 约束提供的方法. 但是比较有意思的是, 复杂场景下, 可以用 具备泛型的 interface 作为 参数的 约束.

在类型推导上, 遵循三个步骤:

  1. non-type parameter 是否合法
  2. type-parameter 推演, 确定其他
  3. type-parameter 替换
  4. type-parameter 是否合法

整体的感觉, 还是偏向 interface + 参数推导 来做的, 相比于之前 contract 的思路, 还是更加容易接受些

缺点

  1. 举个例子,+ - < > = 这种算法表达式没有定义 interface, 目前社区讨论的是 借助 type list 的方式处理, 但是 只能解决基本类型,对于自定义的struct 还是无奈的, 没有比如 rust std:operaion 的各种类型, 但是一定程度上削弱了 泛型的表达能力

  2. 鸡肋: 引入了 any 替换 interface{}, 但是 any 没有任何功能

  3. graph 的例子挺呕心的, 社区应该优化下. 能有个关联类型就好了, 得问问 (尝试优化下)

对比

java

https://juejin.im/post/6844904155316764685 得自己搞下了

rust

参考: