by yijie

最近都在研究类型系统,比如 Haskell, OCaml, Swift, Rust。 还有 C++,都有很强大的类型系统。 昨天突发奇想,想看看 Go 1.18 新增的泛型类型系统如何。 (之前在互联网公司使用很长一段时间的 Go,之前的 Go 的类型系统一直是基于 interface{} 动态派发的,直到 2022 年推出的 1.18,有了泛型,interface 被重新定义了。)

Go 泛型大纲

(只写大纲,细节的东西去官网自己看了。我很喜欢的一句话“这不重要”。)

重新定义 interface

一切的基础:interface 由动态匹配转变为静态约束了。

三种 泛型语法

定义 struct 和 receiver

type S[T constraint] struct {}
func (S[T]) Receive() {}

定义 interface

type I[T constraint] interface {}

定义 function

func F[T constraint] Foo(v T) {}

约束

约束语法的本质是 interface。内置的有 any 和 comparable 两种。还有官方做了一个 constraints 包。

类型推断

Go 目前仅支持 func 的类型推断,其他的 generic struct 和 generic interface 在使用的时候都要提供类型参数。这个行为跟早期的 C++ 一样。

展望

更多泛型

Receiver 不能再有自己的泛型参数了。但这在实际项目中还是挺有用的,例如

type Origin[T any] struct {
    Value T
}

func (o Origin[T]) CompareTo[Y any](other Origin[Y]) bool {}

这样的语法是不能编译的。

当前的匿名的方法、结构、interface 都不能用泛型参数。确实有点不方便。

更强大的类型推断

Go 仅对 func 进行类型推断是不够的。其他静态类型语言的类型推断是很强大的,甚至是很快速的,比如 OCaml, Swift(Haskell, Rust 也非常强大,但是我写得不多,不妄言)。

interface 类型擦除

Go 不支持 interface 泛型参数擦除。

Swift 的 protocol(associatetype) 类型擦除堪称完美,也非常有用。

默认实现

Go 不支持方法的默认实现。这其实跟泛型关系不是很大,虽然可以定义一个 interface,但是不能给 interface 定义一个默认实现,如果写过 swift, rust 就知道我在说什么的。

类型组合推断

举个 swift 的例子:

protocol 飞机 {
    func 起飞()
}

protocol 汽车 {
    func 遛一遛()
}

extension 汽车 where Self: 飞机 {
    var 飞行汽车: Bool {true}
}

这个功能挺有用的,特别在进行复杂数据结构的推理上。不过也许 Go 不打算做这么复杂吧。

参考

  • https://en.wikipedia.org/wiki/Type_system
  • https://go.dev/doc/tutorial/generics

以上内容来源于我的 d2outliner 大纲笔记。