前段时间看到大家在吵一个话题,那就是 Go 语言的类型声明,抠知识抠的非常细了,就是为什么他要放在后面,展开了热烈的讨论。

示例代码如下:

var a []string
var b []string

其实在早年 Go 官方估计已经被问烦了,写过一篇《Go's Declaration Syntax[1]》来具体介绍和说明情况。

为此煎鱼将参考并结合这篇官方资料,带大家一起了解为什么 Go 如此的 “与众不同” ,为什么要把类型放在后面。

类型前置

在业内目前有不少知名语言,也采取的是在声明变量类型时,把类型定义在名字前面。像是 C、C++、C#、Java 等:

int x;
int x = 100;

基本的格式定义:<data_type> <variable_list>;。

上面的声明是一个简单的例子,如果更复杂一些,Go 官方还给出了著名的函数指针的例子:

int (*fp)(int a, int b);

更进一步,如果返回值也是个函数指针类型,就会变成:

int (*(*fp)(int (*)(int, int), int))(int, int)

这已经很难看出来是个 fp 的声明了。

类型后置

前面所举例的类型前置的编程语言,很多都是 C 系列中的一者。类型后置的代表,分别有:Go、Rust、Scala、Kotlin 等。

其实在很多类型后置的编程语言种,会采取变量名+冒号+类型的方式出现。就像 Rust 一样:

let x: i32;

基本的格式定义:

x: int
p: pointer to int
a: array[3] of int

Go 官方参照了这类类型后置的设计,并且为了简洁,进一步去掉了冒号和一些关键字,变成:

var a []string

我们再看回前面 fp 的声明的例子:

int (*(*fp)(int (*)(int, int), int))(int, int)

再对比 Go 语言中就变成了:

f func(func(int,int) int, int) func(int, int) int

两者一对比,Go 语言代码可读性确实更高一些。

思考

后置类别

在类型声明上,实际上分为:变量类型后置、函数返回值后置。两者共同构建了前置还是后置,总不能一个前置,一个后置吧,那得多么的难受。

上方 C 语言和 Go 语言函数指针的例子,所对比带来的代码可读性提高,其实本质上是由函数返回值后置所带来的。

和类型前置、后置没太多直接关系。

核心思想

在类型后置上来讲,Go 官方核心思想是:这种声明方式(从左到右的风格)的一个优点是,当类型变得更加复杂时,它的效果非常好(One merit of this left-to-right style is how well it works as the types become more complex)。

Go 的变量名总是在前,在人的代码阅读上可以保持从左到右阅读,不需要像 C 语言一样在一大堆声明中用技巧找变量名对应的类型。

The Clockwise/Spiral Rule

为此甚至有人写了篇 C 语言的顺时针读法《The Clockwise/Spiral Rule[2]》,有兴趣可以阅读。

如此一对比,Go 语言的类型后置在复杂场景下与 C 语言的对比确实更好一些。

其他因素

类型推导

诸如在类型推导的形式上也会更直观:

func main() {var s1 := "脑子进煎鱼了"var s2 string
}

也是一个可读性提高的问题。

类型和名字谁更重要

不同设计者对谁更重要的理解也不一样。是类型更重要,还是名字更重要呢?

有的人认为是类型,有的人认为是名字。这就真的是千人千面,众口难调了。

C# 的后悔

我们看看其他语言,C# 设计组成员之一,其实在《Sharp Regrets: Top 10 Worst C# Features[3]》中的第五点表达了个人对类型前置、后置的设计教训。

img

核心观点是:从编程和数学两方面来看,都有一个约定,即计算的结果在右侧表示,所以在类 C 语言中,类型在左侧是很奇怪的。

在设计时,C# 本来计划把类型注释放在右边。但考虑到类 C 语言,因此遵循了其他语言的惯例。

总结

实际上该问题的研讨,在 2021 年的现在,大部分 case 都一一被反驳了。类型后置也不是一个与众不同的设计,很多语言都是如此。但既然要讨论 Go 语言,那更多的是站在设计者的角度去考虑

结合 Go 所提供的官方资料,在当年的目的更多的是为了在遇到复杂类型定义时,能保持一定的代码可读性

当然,这不可否认肯定包含 Go 开发团队的主观意识。有兴趣的可以具体挖挖背后的信息。

如果是你,你会希望类型放在前面,还是后面呢,为什****么?

参考资料

[1]

Go's Declaration Syntax: https://go.dev/blog/declaration-syntax

[2]

The Clockwise/Spiral Rule: http://c-faq.com/decl/spiral.anderson.html

[3]

Sharp Regrets: Top 10 Worst C# Features: https://www.informit.com/articles/article.aspx?p=2425867

关注煎鱼,吸取他的知识 

Go 把类型放在变量名后面,是特立独行还是另有机密?相关推荐

  1. C语言的指针符号到底靠近变量类型还是变量名?

    今天在复习数据结构时,C语言实现线性表用到了指针,对指针符号的位置存疑,遂查询了一下: 在C语言中只要使用指针,必然用到* 运算符.然后经常会看到不同的书中*有靠近变量类型的,有靠近变量名称的,很迷惑 ...

  2. Java中数组的定义,怎么发现那个方括号放在变量名前或者后都是正确的?

    int array[]= new int[3]; int[] array= new int[3]; 我运行了都正确?? Java的数组定义支持两种格式: int[] a和int a[] 前者是Java ...

  3. java开发定义一个好的变量名

    如何定义一个好的变量名 在日常编程中最烦恼的就是给变量取名,一段好代码,既要能完美地运行,还要能较容易地维护.这就意味着需要让日后维护代码的人能很快地看懂你的代码,而且,在团队合作中,其他开发者也会经 ...

  4. (转载) 如何定义一个号的变量名

    如何定义一个好的变量名 在日常编程中最烦恼的就是给变量取名,一段好代码,既要能完美地运行,还要能较容易地维护.这就意味着需要让日后维护代码的人能很快地看懂你的代 码,而且,在团队合作中,其他开发者也会 ...

  5. vb变量名的命名规则

    求十分详细的的java变量命名规范 您好,提问者: 在java编程中命名规范是统一的,而且老外发明的东西是没有中文的,严格区分大小写. 规范:以字母.下划线.'$'符号组成,不能以数字开头,声明类跟变 ...

  6. 在c语言中指针变量名前面的*表示其后面的,C语言中的指针

    -------------------------------指针--------------------------------- 指针? 内存单元的编号也叫做地址.既然根据内存单元的 号或地址就可 ...

  7. jstl动态取变量_C语言的变量名

    变量名是用来标识某个内存块的 地址就是地址啦,如是变量名的话,用取地址运算符&就可以得到它标识的内存块的地址, 而指针变量呢,它本身也是一个变量名,只不过它标识的那块内存存放的是一个地址值 变 ...

  8. python变量区分大小写吗_Python变量名是不是区分大小写的

    Python变量名是不是区分大小写的 发布时间:2020-11-10 14:13:23 来源:亿速云 阅读:95 作者:小新 Python变量名是不是区分大小写的?这个问题可能是我们日常学习或工作经常 ...

  9. 深入理解C系列:不同类型变量的变量名和内存间的关系

    有了前面两篇的基础,下面正式开扒变量名和内存的关系,先看一段大家很熟悉的代码: int i;scanf_s("%d", &i); int i;,在这一句就为i分配了内存(但 ...

最新文章

  1. Android studio的深坑 导jar包重复的异常处理
  2. Android之安装常见的一些解决方法
  3. [H5表单]一些html5表单知识及EventUtil对象完善
  4. 【php】命名空间的影响
  5. Sobel算子取代:基于特定点方向的canny边缘检测
  6. winform窗体控件多,加载慢、卡顿的解决办法
  7. php额拍戏,像这种会演戏的演员,给我焊在剧组365天拍戏可以吗?
  8. git提交 本地分支和远程分支断开连接
  9. kafka消息消费有延迟_RabbitMQ与Kafka的技术差异以及使用注意点
  10. scala:Scala class的构造方法与继承
  11. 千兆云路由器Dlink850L10个0Day漏洞成筛子 PoC满天飞 随便拿Root权限
  12. SSH远程管理、参数讲解、xshell使用、scp,sftp,ssh命令(ssh两种方式的密钥验证方...
  13. VS编译错误:error C2143: 语法错误 : 缺少“;”(在“类型”的前面)
  14. 如何修改(显示)文本文档后缀名
  15. 德育知识元素挖掘系统设计 软件工程 spring boot + Vue.js + python机器学习
  16. 计算机弹音乐教程远走高飞,计算器弹歌曲远走高飞 | 手游网游页游攻略大全
  17. SSH 登录指纹验证
  18. js中excel模板下载
  19. 【JS逆向系列】某乎x96参数与jsvmp初体验
  20. 启发式教学的二十种实用方式教学与教学方法的关系

热门文章

  1. Java读写Excel之POI超入门(转)
  2. 很容易学习的JQuery库 : (八) 杂项 noConflict() 方法
  3. 基于9款CSS3鼠标悬停相册预览特效
  4. C#开发微信门户及应用(27)-公众号模板消息管理
  5. ios8 地图不能定位问题的解决办法
  6. Google Maps API 申请方式变更为APIs Console, android手机申请方式
  7. QTP的那些事--XPath的重要使用
  8. PostgreSQL 10.1 手册_部分 II. SQL 语言_第 12 章 全文搜索_12.4. 额外特性
  9. nginx 403 Forbidden
  10. 新浪安装weiphp2.0的方法