设为首页 - 加入收藏 重庆站长网 (http://www.023zz.com)- 国内知名站长资讯网站,提供最新最全的站长资讯,创业经验,网站建设等!
热搜: 为什么 2018 2019 中国
当前位置: 首页 > 运营中心 > 建站资源 > 优化 > 正文

Go语言的奇特语法,你怎么看?

发布时间:2019-04-25 11:29 所属栏目:[优化] 来源:itworld123
导读:刚开始接触Go语言的同学觉得Go语言的语法很特别,尤其是使用C/C++或者Java等语言的同学。比如在C等语言中定义变量的时候类型是在名称前面,而Go语言偏偏要将类型放在变量名称后面,觉得很奇怪等等。下面是原文,对这些奇怪的语法给出了相对官方和靠谱的解

刚开始接触Go语言的同学觉得Go语言的语法很特别,尤其是使用C/C++或者Java等语言的同学。比如在C等语言中定义变量的时候类型是在名称前面,而Go语言偏偏要将类型放在变量名称后面,觉得很奇怪等等。下面是原文,对这些奇怪的语法给出了相对官方和靠谱的解释。

不是为了与众不同。而是为了更加清晰易懂。

Rob Pike 曾经在 Go 官方博客解释过这个问题(原文地址:http://blog.golang.org/gos-declaration-syntax),简略翻译如下(水平有限翻译的不对的地方见谅):

引言

Go语言新人常常会很疑惑为什么这门语言的声明语法(declaration syntax)会和传统的C家族语言不同。在这篇博文里,我们会进行一个比较,并做出解答。

Go语言的奇特语法,你怎么看?

C 的语法

首先,先看看 C 的语法。C 采用了一种聪明而不同寻常的声明语法。声明变量时,只需写出一个带有目标变量名的表达式,然后在表达式里指明该表达式本身的类型即可。比如:

  1. int x; 

上面的代码声明了 x 变量,并且其类型为 int——即,表达式 x 为 int 类型。一般而言,为了指明新变量的类型,我们得写出一个表达式,其中含有我们要声明的变量,这个表达式运算的结果值属于某种基本类型,我们把这种基本类型写到表达式的左边。所以,下述声明:

  1. int *p; 
  2. int a[3]; 

指明了 p 是一个int类型的指针,因为 *p 的类型为 int。而 a 是一个 int 数组,因为 a[3] 的类型为 int(别管这里出现的索引值,它只是用于指明数组的长度)。

我们接下来看看函数声明的情况。C 的函数声明中关于参数的类型是写在括号外的,像下面这样:

  1. int main(argc, argv) 
  2.  int argc; 
  3.  char *argv[]; 
  4. { /* ... */ } 

如前所述,我们可以看到 main 之所以是函数,是因为表达式 main(argc, argv) 返回 int。在现代记法中我们是这么写的:

  1. int main(int argc, char *argv[]) { /* ... */ } 

尽管看起来有些不同,但是基本的结构是一样的。

总的来看,当类型比较简单时,C的语法显得很聪明。但是遗憾的是一旦类型开始复杂,C的这套语法很快就能让人迷糊了。着名的例子如函数指针,我们得按下面这样来写:

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

在这儿,fp 之所以是一个指针是因为如果你写出 (*fp)(a, b) 这样的表达式将会调用一个函数,其返回 int 类型的值。如果当 fp 的某个参数本身又是一个函数,情况会怎样呢?

  1. int (*fp)(int (*ff)(int x, int y), int b) 

这读起来可就点难了。

当然了,我们声明函数时是可以不写明参数的名称的,因此 main 函数可以声明为:

  1. int main(int, char *[]) 

回想一下,之前 argv 是下面这样的

  1. char *argv[] 

你有没有发现你是从声明的「中间」去掉变量名而后构造出其变量类型的?尽管这不是很明显,但你声明某个 char *[] 类型的变量的时候,竟然需要把名字插入到变量类型的中间。

我们再来看看,如果我们不命名 fp 的参数会怎样:

  1. int (*fp)(int (*)(int, int), int) 

这东西难懂的地方可不仅仅是要记得参数名原本是放这中间的

  1. int (*)(int, int) 

它更让人混淆的地方还在于甚至可能都搞不清这竟然是个函数指针声明。我们接着看看,如果返回值也是个函数指针类型又会怎么样

  1. int (*(*fp)(int (*)(int, int), int))(int, int) 

这已经很难看出是关于 fp 的声明了。

你自己还可以构建出比这更复杂的例子,但这已经足以解释 C 的声明语法引入的某些复杂性了。

还有一点需要指出,由于类型语法和声明语法是一样的,要解析中间带有类型的表达式可能会有些难度。这也就是为什么,C 在做类型转换的时候总是要把类型用括号括起来的原因,像这样

  1. (int)M_PI 
Go 的语法

非C家族的语言通常在声明时使用一种不同的类型语法。一般是名字先出现,然后常常跟着一个冒号。按照这样来写,我们上面所举的例子就会变成下面这样:

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

这样的声明即便有些冗长,当至少是清晰的——你只需从左向右读就行。Go 语言所采用的方案就是以此为基础的,但为了追求简洁性,Go 语言丢掉了冒号并去掉了部分关键词,成了下面这样:

  1. x int 
  2. p *int 
  3. a [3]int 

在 [3]int 和表达式中 a 的用法没有直接的对应关系(我们在下一节会回过头来探讨指针的问题)。至此,你获得了代码清晰性方面的提升,但付出的代价是语法上需要区别对待。

【免责声明】本站内容转载自互联网,其相关言论仅代表作者个人观点绝非权威,不代表本站立场。如您发现内容存在版权问题,请提交相关链接至邮箱:bqsm@foxmail.com,我们将及时予以处理。

网友评论
推荐文章