2012年十月月 发布的文章

也谈Go语言声明语法

一直在从事C语言服务端应用开发,对C的变量声明语法早已烂熟于胸,同时也深知复杂的C变量声明十分晦涩难解。记得若干年前还特意花了一些时间研究理解复 杂C变量声明的方法,记忆中这些方法包括:《C专家编程》中提到的“优先级”规则、right-left规则以及顺时针/螺旋形规则等,幸运地是我们日常 开发中少有使用极为复杂的变量声明(如void (*signal (int signo, void (*func) (int)))(int);),但C语言中这一难点却是事实存在的。

对于我这样的习惯了C变量声明语法的程序员来说,Go的变量声明语法显得极端另类,完全与C语言反其道而行之,心中不由产生一丝厌恶。但随着对Go学习和 使用的深入,我逐渐发现Go的这种声明语法在不经意间解决了复杂声明的理解问题,你无需学习什么"优先级"规则,也无需理会什么“right-left” 规则,你只需按从左到右的顺序阅读代码,再复杂的变量声明也可以很轻易地理解。

Go语言为何要采用这种倒序语法呢?Go的设计者Rob Pike的一篇介绍Go声明语法的文章给出了答案,其中谈到了Go声明语法的设计考量。Go的设计者从C体系之外的语言获得启发:将变量名放在签名,类型说明放在后 面。这样更接近于自然语言,例如:

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

b: slice of int

在此基础上,Go的设计者用*、[]等符号替换掉上面的冒号和部分关键字使得声明变得短小,也就形成了Go的声明语法:

var x int
var p *int
var a [3]int

var b []int

我们只需从左向右的顺序阅读代码,即可清晰的理解声明的含义,而不需要像C声明语法那样左右符号都要兼顾,螺旋理解。这里面的*、[n]和[]的含义如下:

*some_type:读作 pointer to some_type
[n]some_type: 读作 array[n] of some_type
[]some_type: 读作 slice of some_type

下面我们通过Go与C的对比来进一步理解Go的声明语法。

简单变量声明

                                           Golang
int x;      <–>      var x int //x has the type int
float x;    <–>      var x float64 //x has the type float64
char c;     <–>      var c byte
//x has the type byte

指针变量声明

C                                            Golang
int *x;     <–>      var x *int //x is a pointer to int
int **p;    <–>      var p **int //p is a pointer to pointer to int 

数组/切片变量声明

C                                            Golang
int a[5];     <-->    var a [5]int //a is an array[5] of int
int a[5][3];  <-->    var a [5][3]int  //a is an array[5] of array[3] of int

                                            var s []int //s is a slice of int(C语言中无slice类型)

函数类型变量声明

C                                            Golang
int (*x)(int, int) 类似于   var x func(int, int) int // x has the type "func(int, int) int"
     

Go中函数为first-class类型,其类型的变量等同于C中的函数指针。

复合声明(复杂声明)

C                                            Golang
int *x[5];   <-->       var x [5]*int //x is an array[5] of pointer to int
int (*x[5])(int, int)   类似于  var x [5]func(int, int) int // x is an array[5] of "func(int, int) int" 

                                                var f func(func(int,int) int, int) func(int, int) int //f has the type "func(func(int,int) int, int) func(int, int) int",这是一个函数类型变量,这个函数类型接收三个参数(其中一个参数是func(int, int)函数类型),并返回另外一个函数类型(func(int, int) int)。

void (*signal (int signo, void (*Afunc) (int))) 类似于  var signal func(signo int, Afunc func(int))

有了上面的例子,signal就无需再作解释了,Go的声明语法可以让我们可以很容易的理解复杂的变量声明。但从可读性角度来看较长的声明依旧不利于代码理解。因此我们还是应该通过type定义一些新类型的方式尽量缩短变量声明的长度,例如:

type Handler func(int)
type SignalHandler func(signo int, handler Handler)
var signal SignalHandler

编程语言进入“拼爹”时代

近期看到一则新闻,说是Microsoft推出了一门开源的编程语言叫TypeScript,该Project的主要负责人是大名鼎鼎的Anders Hejlsberg,就是那个Turbo Pascal Delphi以及C#之父。结合近几年来出现的颇受关注的其他几门编程语言,如GoRustDart等,让我感觉到编程语言似乎进入了"拼爹"时代。

我们来列举一下这几门新兴语言的“老爹”(设计者):

* Go语言 – Robert Griesemer、Rob PikeKen Thompson
这里最著名也最NB的当属Ken Thompson,Unix之父,并与Dennis Ritchie一起创造了最伟大的工业编程语言C图灵奖得主。Rob Pike也是Bell Labs元老,Unix和Plan 9计划的参与者,Limbo语言的设计者之一。至于Robert Griesemer名气似乎小一些,我也不甚熟悉。不过有了前两位,想必Golang就会有足够的号召力了。

* Rust语言 – 来自著名的Mozilla Lab,其主要设计者包括Brendan Eich,Dave Herman以及Graydon Hoare。其中Brendan Eich是JavaScript语言之父。

* Dart语言 – 这门语言的最初两个设计者Lars Bak和Kasper Lund似乎并不著名,但这门语言背后有一个更大的后台,那就是在互联网搜索时代叱诧风云的Google公司。凭借着Google的号召力,围绕在这门语 言周围的Fans也应该为数不少。再考虑这门语言旨在替代JavaScript成为新Html5标准下主力Web开发语言的目标,Dart受到的关注一定 不少。

这里再顺便回顾一下编程语言发展的几个历史时期(个人的一点拙见)。

* 结构化时代
20世纪六七十年代,以C、Fortran、Pascal、Basic为代表的结构化程序设计语言的诞生,标志着编程语言进入了结构化时代。人们逐渐脱离 生产效率低下的汇编,而转移到中级/高级语言行列。最终C以其Unix平台语言的身份胜出,并以其简洁高效的生成代码在二十世纪末期在嵌入式领域独占鳌 头。

* OO时代
随着人们的关注点逐渐向问题域转移,人们迫切需要一门能对现实问题进行更好抽象的语言。面向对象语言逐渐进入人们的视野。代表语言包括C++、Ada、 Delphi、Java以及C#等。C++和Delphi因其卓越的性能以及不熟的IDE支持,在桌面程序设计领域(包括PC游戏领域)成为主角。 Java则在企业应用兴起后逐渐发展壮大,最终成为OO时代的No.1。

* Web时代
随着全球互联网时代的到来,诸多Web语言走到了前台,代表语言包括PHP、JavaScript、ASP等,另外一些轻巧且生产高效的脚本语言也开始被 大家所青睐,它们既能轻松完成系统管理的任务又支持Web开发,这其中的代表语言包括:Perl、Python、Ruby、Lua等。

* 新时代
这里暂且叫作新时代,这个时代有几个特点:
1) 传统语言不断翻新,融入新特性
C和C++于今年发布了C11标准;Java也给出了JDK8规范的发布时间表。在新标准中,这些传统语言也加入了一些适宜这个时代开发的新特性,比如函数范式以及对多核并行程序的支持。

2) 终端开发语言迅速崛起
随着iPhone和Android的迅速发展,终端开发语言逐渐壮大,最典型的代表则是Objective-C,依靠苹果公司这棵大树,与C++同时期的Objective-C仿佛坐着火箭一般迅速串升到编程语言排行榜前3甲的位置。

3) 函数式语言的回归
以Common Lisp、Haskell、Erlang等为代表的函数式程序设计语言重装归来,誓与传统命令式语言一绝高下。函数式范型语言的回归意义似乎不在于占领更 大的市场,而是在于其对后续新兴编程语言的设计决策的影响,甚至像C++这样的老牌OO语言在新规范中也加入了函数式范型的支持。

4) "拼爹"的新兴语言
就如上面所讲的,一些传统语言的设计大师汲取之前语言的设计经验和教训后,二次出手,设计出了以Go、Rust、TypeScript等为代表的新兴语 言,并且他们的号召力对这些新兴语言有着很大的影响。这些语言站在巨人的肩膀上,获得了重新的设计,使得语言能满足未来市场对应用程序以及硬件设备的要 求。这些语言将会是未来10年乃至20年间编程领域的主力。

目前的确是编程语言的一个新时代,更是一个百花齐放,百家争鸣的时代。作为这个时代的程序员是幸运的,因为有这么多优秀语言可供学习和选择;同时也是"不幸的",有这么多语言要去学习(当然也可以不学^_^)。

欢迎使用邮件订阅我的博客

输入邮箱订阅本站,只要有新文章发布,就会第一时间发送邮件通知你哦!




这里是Tony Bai的个人Blog,欢迎访问、订阅和留言!订阅Feed请点击上面图片

如果您觉得这里的文章对您有帮助,请扫描上方二维码进行捐赠,加油后的Tony Bai将会为您呈现更多精彩的文章,谢谢!

如果您希望通过微信捐赠,请用微信客户端扫描下方赞赏码:


如果您希望通过比特币或以太币捐赠,可以扫描下方二维码:

比特币:


以太币:


如果您喜欢通过微信App浏览本站内容,可以扫描下方二维码,订阅本站官方微信订阅号“iamtonybai”;点击二维码,可直达本人官方微博主页^_^:



本站Powered by Digital Ocean VPS。

选择Digital Ocean VPS主机,即可获得10美元现金充值,可免费使用两个月哟!

著名主机提供商Linode 10$优惠码:linode10,在这里注册即可免费获得。

阿里云推荐码:1WFZ0V立享9折!

View Tony Bai's profile on LinkedIn


文章

评论

  • 正在加载...

分类

标签

归档











更多