
1.1 Go语言基础
1.1.1 基础语法
1 Go语言标记
Go程序由关键字、标识符、常量、字符串、符号等多种标记组成。
2 行分隔符
在Go程序中,一般来说一行就是一个语句,不用像Java、PHP等语言那样需要在一行的最后用英文分号“;”结尾。例如,如下的写法是两个语句。

3 注释
在Go程序中,注释分为单行注释和多行注释。
1)单行注释。单行注释是最常见的注释形式之一,以双斜线“//”开头的单行注释,可以在任何地方使用,形式如下。

2)多行注释。多行注释也叫块注释,通常以“/∗”开头,并以“∗/”结尾,形式如下。

4 标识符
标识符通常用来对变量、类型等程序实体进行命名。一个标识符实际上就是一个或多个字母(A~Z和a~z)、数字(0~9)、下画线“_”组成的字符串序列,要求第1个字符不能是数字或Go程序的关键字。
5 字符串连接
Go语言的字符串可以通过“+”号实现字符串连接。
6 关键字
在Go语言中有25个关键字或保留字,见表1-1。
表1-1

除以上的这些关键字外,最新版本的Go语言中有三十几个预定义标识符,它们可以分为如下3类。
(1)常量相关预定义标识符
true、false、iota、nil。
(2)类型相关预定义标识符
int、int8、int16、int32、int64、uint、uint8、uint16、uint32、uint64、uintptr、float32、float64、complex128、complex64、bool、byte、rune、string、error。
(3)函数相关预定义标识符
make、len、cap、new、append、copy、close、delete、complex、real、imag、panic、recover。
7 Go语言的空格
在Go语言中,变量的声明必须使用空格隔开。一般来说,在开发过程中可以运用编辑器的格式化命令快速格式化后,程序的变量与运算符之间会加入空格。
1.1.2 变量
1 声明
Go语言是静态类型语言,因此变量(variable)是有明确类型的,编译器也会检查变量类型的正确性。声明变量的一般形式是使用var关键字,形式如下。

其中,var是声明变量的关键字,name是变量名,type是变量的类型。需要注意的是,Go语言和其他编程语言不同,Go语言在声明变量时将变量的类型放在变量的名称之后。例如在Go语言中,声明整型指针类型的变量,格式如下。

当一个变量被声明之后,系统自动赋予它该类型为0值或空值:例如int类型为0、float类型为0.0、bool类型为false、string类型为空字符串、指针类型为nil等。
变量的命名规则遵循骆驼命名法,即首个单词小写,每个新单词的首字母大写。命名规则不是强制性的,开发者可以按照自己的习惯制定自己的命名规则。
变量的声明形式分为标准格式、批量格式、简短格式3种形式。
(1)标准格式
Go语言变量声明的标准格式如下。

变量声明以关键字var开头,后置变量类型,行尾无须分号。
(2)批量格式
Go语言还提供了一个更加高效的批量声明变量的方法——用使用关键字var和括号将一组变量定义放在一起,示例代码如下。

(3)简短格式
除var关键字外,还可使用更加简短的变量定义和初始化语法,格式如下。

需要注意的是,简短模式(Short Variable Declaration)有以下限制。
● 只能用来定义变量,同时会显式初始化。
● 不能提供数据类型。
● 只能用在函数内部,即不能用来声明全局变量。
和var形式声明语句一样,简短格式变量声明语句也可以用来声明和初始化一组变量。

因为简洁和灵活的特点,简短格式变量声明被广泛用于局部变量的声明和初始化。var形式的声明语句往往用于需要显式指定变量类型的情况,或者因为变量稍后会被重新赋值而初始值无关紧要的情况。
2 赋值
1)给单个变量赋值。给变量赋值的标准方式如下。

2)给多个变量赋值。给多个变量赋值的标准方式如下。

或者,多个变量和变量值在同一行,中间用英文逗号“,”隔开,形式如下。

例如,声明一个用户的ID userId、名字username、得分score,可以通过如下方式批量赋值。

或者另外一种如下形式。

最简单的形式如下。

以上三者是等价的。当交换两个变量时,可以直接采用如下格式。

3 变量的作用域
Go语言中的变量分为局部变量和全局变量。
1)局部变量。在函数体内声明的变量称为局部变量,它们的作用域只在函数体内,参数和返回值变量也是局部变量。
2)全局变量。在函数体外声明的变量称为全局变量。全局变量可以在整个包甚至外部包(被导出后)使用,也可以在任何函数中使用。
1.1.3 常量
1 常量的声明
常量的声明格式和变量的声明类似,形式如下。

例如声明一个常量e的方法如下。

2 常量生成器iota
常量声明可以使用常量生成器iota初始化。iota用于生成一组以相似规则初始化的常量,但是不用每行都写一遍初始化表达式。在一个const声明语句中,在第1个声明的常量所在的行,iota将会被置为0,然后在每一个有常量声明的行加1。
1.1.4 运算符
运算符是用来在程序运行时执行数学或逻辑运算的符号。在Go语言中,一个表达式可以包含多个运算符,当表达式中存在多个运算符时,就会遇到优先级的问题。这个就由Go语言运算符的优先级来决定。例如以下表达式。

Go语言有几十种运算符,被分成十几个级别,有的运算符优先级不同,有的运算符优先级相同。Go语言运算符优先级和结合性见表1-2。
表1-2

注意:在以上表格中,优先级值越大,则表示优先级越高。
1.1.5 流程控制语句
1 if…else(分支结构)
在Go语言中,关键字if是用于测试某个条件(布尔型或逻辑型)的语句。如果该条件成立,则会执行if后由大括号{}括起来的代码块,否则就忽略该代码块继续执行后续的代码。
如果存在第二个分支,则可以在上面代码的基础上添加else关键字以及另一代码块。这个代码块中的代码只有在条件不满足时才会执行。if{}和else{}中的两个代码块是相互独立的分支,两者只能执行其中一个。一般来说,if…else分支的数量是没有限制的。但是为了代码的可读性,还是不要在if后面加入太多的if…else结构。如果必须使用这种形式,则尽可能把先满足的条件放在前面。
关键字if和else之后的左大括号“{”必须和关键字在同一行。如果使用了if…else结构,则前段代码块的右大括号“}”必须和if…else关键字在同一行。这两条规则都是被编译器强制规定的,否则编译不能通过。
2 for循环
Go语言的for循环有3种形式,只有其中的一种使用分号。
(1)和C语言的for一样

(2)和C的while一样

(3)和C的for(;;)一样

以上3种形式的说明如下。
● init:一般为赋值表达式,给控制变量赋初始值。
● condition:关系表达式或逻辑表达式,循环控制条件。
● post:一般为赋值表达式,给控制变量增量或减量。
for语句执行过程如下。
1)先对表达式for init; condition; post { }赋初始值。
2)判别赋值表达式init是否满足给定条件,若其值为真,满足循环条件,则执行循环体内语句,然后执行post,进入第二次循环,再判别condition;如果判断condition的值为假,不满足条件,就终止for循环,执行循环体外语句。
在使用循环语句时,需要注意以下几点。
● 左大括号{必须与for处于同一行。
● Go语言中的for循环与C语言一样,都允许在循环条件中定义和初始化变量。唯一的区别是,Go语言不支持以逗号为间隔的多个赋值语句,必须使用平行赋值的方式来初始化多个变量。
● Go语言的for循环同样支持用continue和break来控制循环,但是它提供了一个更高级的break,可以选择中断哪一个循环。
在for循环中,如果循环被break、goto、return、panic等语句强制退出,则之后的语句不会被执行。
3 for…range循环
for-range循环结构是Go语言特有的一种的迭代结构,在许多情况下都非常有用。for…range可以遍历数组、切片、字符串、map及通道(channel)。
for-range循环结构的一般形式如下。

4 switch…case语句
Go语言switch…case语句要比C语言的更加通用,表达式的值不必为常量,甚至不必为整数。case按照从上往下的顺序进行求值,直到找到匹配的项。可以将多个if…else语句改写成一个switch…case语句。Go语言中的switch…case语句使用比较灵活,语法设计尽量以使用方便为主。
Go语言改进了switch…case语句的语法设计:case与case之间是独立的代码块,不需要通过break语句跳出当前case代码块以避免执行到下一行。
同时,Go语言还支持一些新的写法,比如一分支多值、分支表达式。
(1)一分支多值
当需要多个case放在一起时,可以写成下面这样。

以上代码的运行结果如下。

一分支多值case表达式使用逗号分隔。
(2)分支表达式
case语句后既可以是常量,也可以和if一样添加表达式,示例如下。

注意:这种情况时switch后面不再需要加判断变量。
5 goto语句
在Go语言中,可以通过goto语句跳转标签,进行代码间的无条件跳转。另外,goto语句在快速跳出循环、避免重复退出方面也有一定的帮助。使用goto语句能简化一些代码的实现过程,示例如下。

6 break语句
Go语言中的break语句可以结束for、switch和select的代码块。另外还可以在break语句后面添加标签,表示退出某个标签对应的代码块。添加的标签必须定义在对应的for、switch和select的代码块上,示例如下。


7 continue语句
Go语言中continue语句可以结束当前循环,开始下一次的循环迭代过程。它仅限在for循环内使用。在continue语句后添加标签时,表示开始标签对应的循环,示例如下。
