Go泛型主要设计者出面说明使用泛型的时机

底层使用Go应用程序的知名无服务器数据库平台Planetscale,在Go 1.18刚发布不久,其工程师便针对新的泛型功能进行测试,并在自家博客发布文章提到,Go的泛型功能可能使程序代码变慢,而该篇文章在网络被热烈讨论,因为Go开发者盼望了泛型功能许久,最后拿到的却与期待有所落差。

而Google技术总监同时也是Go泛型主要设计者的Ian Lance Taylor,则在Go博客搬出2021年,他在Go Day与GopherCon的讲题When To Use Generics,来说明Go泛型的正确使用时机。

Planetscale的工程师提到,之所以Go泛型可能使程序代码变慢的原因,是因为Go泛型的实例,并非使用完全单态化(Monomorphization),而是采用了一种称为GCShape Stenciling with Dictionaries的部分单态化技术,该方法虽然可大幅减少程序代码的量,但是却会在特定的情况下,使程序代码变慢。

而Ian Lance Taylor提到,Go的程序开发通用准则,要开发者通过编写程序代码来撰写Go程序,而非定义类型,因此谈到泛型,要是开发者通过定义类型参数约束来撰写程序,那一开始就走错路了,应该从编写函数开始,而在之后就能够自然地添加类型参数,因为类型参数在该情况展现的好处将会非常明显。

Ian Lance Taylor列出4个类型参数可能有用的情况,第一是使用语言定义的特殊容器类型,进行操作的函数,像是slice、map和channel,当函数具有这些类型的参数,并且函数程序代码没有对元素类型进行任何特定假设,则类型参数可能有用。

另一个参数类型有用的情况,是用于通用数据结构,像是连接串行(Linked List)或是二元树(Binary Tree),这些类似slice或map但又非语言内置的通用数据结构。第三则是类型参数首选函数而非方法,开发者可以将方法转换成函数,会比将方法添加到类型中简单的多。最后一个类型参数可发挥效果的情况,是不同类型需要实现通用方法,且不同类型的实例看起来都相同时。

Ian Lance Taylor也提醒了不适合使用类型参数的时机,包括不要用类型参数代替接口类型(Interface Type),且当方法实例不同时,也不要使用类型参数。他提到,Go 1.18实例泛型的方法,使得类型参数通常不会比接口类型快,因此不需要为了执行速度更改程序代码。

Ian Lance Taylor最后给出了简单的泛型使用方针,就是当开发者发现自己多次编写相同的程序代码,而副本不同之处的唯一区别,仅在于使用了不同类型,便可以考虑使用类型参数。