Go语言学习教程之声明语法(译)

2019-11-10 11:25:53王旭

然后我们再来看看如果我们将入参变量名去掉的情况下 fp 函数的声明是怎么样的:

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

无论将变量名放在内部的哪里都不那么清晰明了。对于第一个入参:

int (*)(int, int)

我想这不太容易能一眼看出是在声明一个指向函数的指针。再进一步,如果我们的返回值也是一个函数指针呢?

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

这根本就看不清声明出来的 fp 到底是个啥玩意。。。

你自己也可以构造出更多这类详细的例子,但是这些都说明了 C 的声明语法可能引入的一些困难。

不过还有一点需要提出。因为类型和声明的语法是相同的,所以解析中间类型的表达式是很困难的。这就是为什么 C 的类型转换总是用括号括起来:

(int)M_PI

Go 语法

非 C 家族的编程语言通常使用不同的声明类型的语法:变量名通常放在前面,然后紧跟着一个冒号。因此我们上面的例子就变成了这样:

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

这些声明是明确的,如果从左往右读你会发现也是详细的。Go 语言从中得到了启发,但为了简洁起见,删除了冒号和一些关键字:

x int
p *int
a [3]int

这个例子中 [3]int 与如何在表达式中使用 a 这两者似乎没有直接的对应。(后面一小节中我们会讲到指针的。)你可以通过单独的语法来获得清晰的结果。

现在让我们考虑下函数。让我们把这个声明写成 Go 的形式,尽管在 Go 中真正的 main 函数是没有入参的:

func main(argc int, argv []string) int

表面上这和 C 语言并没什么不同,除了将字符数组改成了字符串形式。但是从左往右读起来却很顺畅:

函数 main 需要传入一个整型和字符串切片并且返回一个整型。(译者注:直到译者看到这篇文章,译者才发现原来这么写读起来竟这么顺畅。。。)

即便舍去变量名还是很明确——因为对于类型声明上没有位置的变化,所以也没有什么困惑。

func main(int, []string) int

这种从左到右的风格有一个优点:就算类型变得越来越复杂,这种方式还是表现得很得当。

举个声明函数变量的例子(类似在 C 语言中的函数指针):

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

或者如果 f 返回的也是一个函数(译者注:边写边读你会再次惊讶于这丝滑般的顺畅感。。。):

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

从左到右依然读起来很顺畅,并且当变量名被声明的时候也很明显。