Go 泛型有没有可能在后期改为 <> 尖括号?

2024年 3月 4日 55.1k 0

大家好,我是煎鱼。

最近有一个社区朋友反馈他在某乎上看到一个提问,内容是如标题,对于 Go 泛型的标识符  不太满意,想看看 Go 以后有没有机会改。

问题上的原话是:

一直对 Go 语言的泛型使用 [] 中括号耿耿于怀,[] 中括号在视觉上很难有辨识度,尤其是和切片在视觉上不具有明显区别,当泛型类型约束是切片时更是灾难,对此一直久久不能释怀,那么 Go 官方在后续版本迭代中是否会考虑新增 来表示泛型,也就是说 [] 和 都能表示泛型,由开发者自己决定采用哪个。

考虑到以前的很多同学没了解过 Go 设计的历史,我又翻了出来。

快速温习

针对泛型而言,我们做一个快速的温习。泛型允许程序员在强类型语言中编写代码时,使用一些以后才确定的类型,其在真正实例化时才会为这些参数指确定类型。

简单来讲,泛型就是参数化多态。其可根据实参类型生成不同的版本,支持任意数量的调用:

func F(a, b T) T{ return a+b }

// T 为 int
F(1, 2)

// T 为 string
F("1", "2")

在编译时期编译器便确定其 T 的入参类型。

为什么不使用尖括号

很多同学在讨论的一个问题,那就是 “为什么 Go 泛型不像 C++ 和 Java 那样使用尖括号?,也出现了 “Go 一直标榜业界工程实践类的榜样,为什么就是不用尖括号” 的言论?

思考问题我们不只看表面,官方说不行,那么我们可以倒推来看,看看 Go 语言就用尖括号:

func print(list []T) {

print(numbers)
print(strings)
print(floats)

普通的函数声明看上去似乎结构清晰,没有什么大问题的。接着往下看:

a := w  (z)

我们继续把代码演进一下,简洁一点:

a, b := w  (z)

这时候就犯难了,不仅编译器难以解析,人也很难判别,到底指的是:

a := w  (z)

又或是:

a, b := w(z)

从上述代码来看,使用尖括号难以分别,因为没有类型信息,就无法确定赋值的右侧是一对表达式 w < x 和 y > (z),还是返回两个结果值 w(z) 的泛型函数实例化和调用,其存在歧义。

如果要解决还要引入新的约束,可能会破坏 Go1 的兼容性承诺,这显然是违反 Go 的规范的,在这届核心团队中是无法推进的。

为什么不使用括号

其实最早 Go 泛型的版本是使用了括号的模式,虽然能用,但是用括号会引入新的解析歧义。例如:

var f func(x(T))

从语法上来讲,你无法识别他是未命名参数的 x(T) 函数,还是类型名为参数的 (T) 函数。

同时 Go 语言还存在强制类型转换这一语法,假设代码是 []T(v1) 和 []T(v2){} ,那么你在开括号处,就无法得知其是否代表类型转换。

甚至在函数的完整声明上,我们都会感到困惑:

func F(T any)(v T)(r1, r2 T)

函数入参、泛型、返回值声明均都是括号,造成了语义不清,这显然也是不合理的。

为什么不使用书名号

书名号,也就是:«»。Go 核心团队表示过,不想使用非 ASCII,未来更没打算支持这类情况。

一些争议

网上也有社区里的同学对不支持 Go 官方的尖括号 的说法不是很认可。

例如,前面提到的 Go 里泛型用尖括号会冲突的这个写法:

v1,v2 := ad

Go 核心团队表示说比较为难。

但网友 @Ninsun 同样甩出了 C++ 泛型的用法下是 OK 的。如下图:

图片

因此有许多社区同学表示,Go 不想用尖括号就是懒得处理,嫌编译器 parser 不好写。

总结

现在来看 Go 已经不太可能在后期将泛型改为 尖括号了。毕竟,米已成炊。泛型也已经有了定论好几年了,尖括号早已被否决。

另外 Go 核心团队显然不希望使用尖括号写法,这样会造成明确语义冲突,也不希望花费大量功夫去重新调整编译器。

还剩唯一一种可能性,那就是 Go 核心团队大换血...(难)

相关文章

JavaScript2024新功能:Object.groupBy、正则表达式v标志
PHP trim 函数对多字节字符的使用和限制
新函数 json_validate() 、randomizer 类扩展…20 个PHP 8.3 新特性全面解析
使用HTMX为WordPress增效:如何在不使用复杂框架的情况下增强平台功能
为React 19做准备:WordPress 6.6用户指南
如何删除WordPress中的所有评论

发布评论