Go语言 声明语法

1 概述


Go语言与C系列语言的声明语法不同,此文比较了两种声明方式,并且解释了Go语言的声明为何如此。

2 C 语法


C采用了一种独特且聪明的声明语法。没有使用特殊的语法来描述类型,而是使用了一个涉及被声明项的表达式,然后说明此表达式的类型。

int x;

note:声明x未int,即表达式’x’具有类型int。

通常,为了给新变量编写类型类型,编写一个涉及此变量的表达式,此表达式的结果为基础类型,然后将基础类型放在左侧,表达式放在右侧。

int *p
int a[3]

note:p是int的指针,因为表达式’*p’的类型为int。
note:a是int的数组,因为表达式’a[3]'的类型为int。

C的函数声明最初将参数类型写在括号外,即:

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

note:main是一个函数,因为表达式’main(argc, argv)'返回一个int。

现在,通常写为:

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

不过基础结构相同。

这是一个适用于简单类型的聪明语法,但是很快就令人产生困惑。最有名的例子是声明一个函数指针。

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

note:fp是一个函数指针,因为表达式’(*fp)(a, b)'将会调用一个函数然后返回int。

如果此时,fp的参数也包含函数指针,此时代码就将变得难以阅读。

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

当声明一个方法时,可以将参数省略,所以,main可以声明为:

int main(int, char *[])

而argv的原本的声明如下:

char *argv[]

即,省略参数生命类型,会将处于声明中间位置的参数名称去除来构建类型。虽然可以通过将名称放入类型char*[]的方式声明,但这样也不明显。

如果将fp的声明中参数的名称去除,声明如下:

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

此时难以看出参数名称的位置,并且难以看出它是一个函数指针。

如果返回类型也是一个函数指针,此时便很难看出此声明与fp有关。

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

除此之外,由于类型与声明语法相同,在中间类型的表达式解析起来就十分困难。这也是C转化总是将类型用括号括起来的原因。

(int)M_PI

3 Go 语法


C系类之外的语言同时在声明时采用不同的语法。一种可行的方案是,名称通常在前,后跟冒号。表现如下:

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

note:此语言为虚构的说明性语言。

Go根此得到灵感,并且出于简洁性需要,将关键字与分号去除:

x int
p *int
a [3]int

[3]int的形式与如何在表达式中使用并没有直接的关联。这样,通过单独语法便获得了简洁性。

据此声明机制,将main函数以Go写出便如下:

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

虽然表面上看,此形式与C差距不大,除了将char数组转为strings,安实它的可读性较高:
main函数获取一个int与一份string,然后返回一个int。

即使删除参数名称,此声明依然很清晰。由于参数名称位于首位,所以不会令人困惑。

func main(int, []string) int

这种从左到右风格的优先会在类型变得复杂时体现出来。
以下为一个函数变量的声明(类似于C中的函数指针)。

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

如果返回一个函数,也依然能够保持整洁性。具体哪一个名称被声明也十分明确,名称位于首位。

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

类型语法与表达式语法之间的区别使得在Go中编写调用闭包十分容易。

sum := func(a, b int) int { return a+b} (3, 4)

4 指针


指针是证明规则的例外。注意,在数组与切片中,Go类型语法将方括号放在类型的左侧,而表达式语法将其放在表达式的右侧。

var a[]int
x = a[1]

Go的指针使用了C的符号,但是不能做类似于数组的反转。因为这样会与乘法混淆。

var p *int
x = *p

指针符号本可以使用Pascal的^,例如

var p ^int
x = p^

也许应该这么设计(并且选择另一个操作符用于异或),因为类型与表达式上的前缀星号令许多方面的事情都变得复杂。

翻译源:Go 博客

你可能感兴趣的:(Go语言,Go,声明语法)