12.2 基于合约的泛型
本节内容提供一个线上演讲:YouTube 在线 Google Slides 讲稿
TODO: 需要补充并丰富描述
12.2.1 泛型问题的本质
- 泛型从本质上是一个编译期特性
- 「泛型困境」其实是一个伪命题
- 牺牲运行时性能的做法显然不是我们所希望的
- 不加以限制的泛型机制将严重拖慢编译性能
- 什么时候才能决定一个泛型函数应该编译多少份不同的版本?
- 不同的生成策略会遇到什么问题?
- 加以限制的泛型机制将提高程序的可读性
- 如何妥当的描述对类型的限制?
12.2.2 合约函数
合约是一个描述了一组类型且不会被执行的函数体。
|
|
关键设计
- 在合约中写 Go 语句对类型进行保障
- 甚至写出条件、循环、赋值语句
评述
- 复杂的合约写法(合约内的代码写法可以有多少种?)
- 「一个不会执行的函数体」太具迷惑性
- 实现上估计是一个比较麻烦的问题
12.2.3 合约条件集
合约描述了一组类型的必要条件。
关键设计
- 使用方法及穷举类型来限制并描述可能的参数类型
- comparable/arithmetic 等内建合约
评述
- 这样的代码合法吗?
- _ = Max(1.0, 2)
- 如何写出更一般的形式?
- 可变模板参数的支持情况缺失(后面会提)
- 没有算符函数、重载
|
|
类型参数可能出现的位置:
声明 | 写法 |
---|---|
函数 | func F(type T C)(params ...T) T { … } |
结构体 | type S(type T C) struct { … } |
接口 | type I(type T C) interface { … } |
合约的形式,例:
|
|
12.2.4 合约与参数化接口的区别
思考:
- 接口 Interface 是一组方法,描述了值
- 合约 Contract 是一组条件,描述了类型
- 加上类型参数的接口 —— 参数化的 I(type T C) 的与合约的本质区别是什么?
基于合约的参数化函数的写法:
|
|
基于参数化结构的参数化函数的写法:
|
|
合约 C(T) 的本质是参数化接口 I(type T C) 的语法糖,一个更复杂的例子:
|
|
|
|
12.2.5 示例程序
例1: 泛型式排序
|
|
例2: 泛型式 MapReduce
|
|
例3: 泛型式栈
|
|
例4: 泛型式散列表
|
|
例4: 泛型式扇入扇出负载均衡
|
|
|
|
|
|