当前位置: 首页 > 科技观察

为什么Go语言把类型放在最后?

时间:2023-03-13 13:26:06 科技观察

本文转载自微信公众号《我的脑子是炸鱼》,作者陈建宇。转载本文请联系脑筋急转弯公众号。大家好,我是炸鱼。前段时间看到大家在争论一个话题,就是Go语言的类型声明,知识讲的很详细,所以才放到后面,开始热烈讨论。示例代码如下:vara[]stringvarb[]string其实早些年,Go官方大概是问腻了,写了一篇文章《Go's Declaration Syntax[1]》来详细介绍和解释情况。为此,建宇将参考并结合这份官方资料,带大家了解为什么Go如此“与众不同”,为什么类型会被抛在后面。类型前缀业界知名的语言有很多,在声明变量类型时,也采用在名称前定义类型的方法。如C、C++、C#、Java等:intx;intx=100;基本格式定义:;。上面的声明是一个简单的例子。如果再复杂一点,Go官方还举了一个著名的函数指针的例子:int(*fp)(inta,intb);更进一步,如果返回值也是函数指针类型,就会变成:int(*(*fp)(int(*)(int,int),int))(int,int)是fp的声明。上面举例的很多类型前缀的编程语言都是C系列的其中之一。后置类型的代表有:Go、Rust、Scala、Kotlin等。其实在很多编程语言中,类型放在类型后面的地方,都会以变量名+冒号+类型的形式出现.就像Rust:letx:i32;vara[]string基本格式定义:x:intp:pointertointa:array[3]ofintGo官方参考了这种类型的后置设计,进一步去掉了冒号和一些关键字就变成了:vara[]string我们再回顾一下前面fp声明的例子:int(*(*fp)(int(*)(int,int),int))(int,int)再对比Go语言,就变成了:ffunc(func(int,int)int,int)func(int,int)int两者相比较,Go语言代码的可读性确实更高。思考后置类在类型声明方面,其实分为:变量类型的后置和函数返回值的后置。两者共同构成前或后,总不能一前一后吧,那多难受啊。上面C语言和Go语言中函数指针的例子,通过对比带来的代码可读性的提升其实本质上是函数的返回值带来的。与类型介词和后置词没有太大的直接关系。核心思想在类型后置方面,Go官方的核心思想是:这种声明方式(从左到右的风格)的一个优点是当类型变得更复杂时效果很好(一个优点是从左到右的风格是它随着类型变得更复杂而工作的好坏)。Go的变量名总是在前面,人们在阅读代码时可以一直从左到右阅读。不需要像C语言那样在大量的声明中去使用技巧去寻找一个变量名对应的类型。Clockwise/SpiralRule甚至用C语言写了一个顺时针读法《The Clockwise/Spiral Rule[2]》,有兴趣的可以看看。这样一对比,Go语言的类型后缀在复杂场景下确实比C语言好。其他因素的类型推导,比如类型推导的形式也会更加直观:funcmain(){vars1:="Mybrainisfryingfish"vars2string}也是提高可读性的问题。哪个更重要,类型还是名称?不同的设计师对于谁更重要有不同的理解。类型更重要,还是名称更重要?有人认为是类型,有人认为是名字。这真是千人千面,一言难尽。C#的遗憾再看看其他语言,C#设计组的一位成员,其实《Sharp Regrets: Top 10 Worst C# Features[3]》中的第五点表达了他个人关于前类型和后类型的设计经验。其核心思想是:从编程和数学上都有一个约定,计算的结果表示在右边,所以在类C语言中,类型在左边是很奇怪的。在设计的时候,C#本来是打算把类型注解放在右边的。但是考虑到类C语言,其他语言的约定俗成。总结这个问题的实际讨论,2021年,大部分案例都被一一反驳了。类型后缀也不是一种独特的设计,就像在许多语言中一样。但是既然要讨论Go语言,更多的是站在设计者的角度去考虑。结合Go官方提供的资料,当时的目的更多的是在遇到复杂的类型定义时,保持一定的代码可读性。当然,不可否认的是,这必然包含了Go开发团队的主观意识。有兴趣的可以深挖背后的资料。如果是你,你希望字体在前面还是后面?为什么?参考资料[1]Go的声明语法:https://go.dev/blog/declaration-syntax[2]顺时针/螺旋规则:http://c-faq.com/decl/spiral.anderson.html[3]强烈的遗憾:10大最差的C#功能:https://www.informit.com/articles/article.aspx?p=2425867