Go 词法元素

admin
admin 2020年02月11日
  • 在其它设备中阅读本文章

Go 语言的 词法元素 包括 标识符 (identifier)、 关键字 (keyword)、 操作符 (operator)、 分隔符 (delimiter)、 字面量 (literal),它们是组成 Go 语言代码的最基本单位。

一、标识符

标识符是用来命名各种变量、方法、函数等程序实体的字符序列,一个标识符实际上就是一个或是多个 Unicode 字母(Unicode 标准 8.0 中的 Lu、Ll、Lt、Lm 和 Lo 分类中的字符)、Unicode 数字(Unicode 标准 8.0 中的 Nd 数字字符分类中的字符)和 _ 组成的字符序列,但是第一个字符必须是 Unicode 字母或 _
_ 是一个特殊的标识符,称为 空白标识符 ,它可以像其他标识符那样用于变量的声明或赋值(任何类型都可以赋值给它),但任何赋给这个标识符的值都将被抛弃,因此这些值不能在后续的代码中使用,也不可以使用_ 作为变量对其它变量进行赋值或运算。
一个由 Unicode 大写字母开头的标识符称为 导出标识符 。这里导出可以被理解为公开(public)。其它(即非 Unicode 大写字母开头的)标识符称为 非导出标识符 。非导出可以被理解为私有(private)。非导出有时候也被称为未导出。
在使用标识符之前必须进行声明,声明一个标识符就是将这个标识符与常量、变量、类型、函数或者代码包绑定在一起。在同一个代码块内标识符的名称不能重复。

命名标识符时需要注意以下几点:

  • 标识符的命名要尽量采取简短且有意义;
  • 不能和标准库中的包名重复;
  • 为变量、函数、常量命名时采用驼峰命名法,例如 stuName、getVal;

在 Go 语言中还存在着一些特殊的标识符,叫做 预定义标识符 ,一共有 36 个,包括

  • 所有基本数据类型,即 int、int8、int16、int32、int64、uint、uint8、uint16、uint32、uint64、float32、float64、complex64、complex128、bool、byte、uintptr、string
  • 常量 true、false、iota,零值 nil
  • 所有的 内建函数 ,即 append、cap、close、copy、complex、real、imag、len、make、new、panic、print、println 和 recover

二、关键字

关键字 是被编程语言保留的字符序列,被 Go 语言赋予了特殊含义,用来帮助编译器理解和解析源代码的单词。共有 25 个包括:

  • 代码元素声明:const、func、import、package、type 和 var
  • 组合类型的字面表示:chan、interface、map 和 struct
  • 程序流程控制:break、case、continue、default、else、fallthrough、for、goto、if、range、return、select 和 switch
  • 特殊的流程控制:defer 和 go

之所以刻意地将 Go 语言中的关键字保持的这么少,是为了简化在编译过程中的代码解析。和其它语言一样,关键字不能够作标识符使用。

三、字面量

简单来说,字面量就是 的一种标记法。但是,在 Go 中,字面量的含义要更加广泛一些。有以下 3 类。
1、用于表示基础数据类型值的 值字面量 。这是最常用的一类字面量,例如,表示浮点数类型值的 12E-3。
2、用于构造各种自定义的复合数据类型的 类型字面量。例如,下面的字面量定义了一个名称为 Name 的结构体类型:

type Name struct {
    Forename    string
    Surname     string
}

3、用于表示复合数据类型值的 复合字面量,它可以用来构造 struct(结构体)、array(数组)、slice(切片)和 map(字典)类型的值。复合字面量一般由类型以及被花括号包裹的复合元素的列表组成。例如,下面的复合字面量构造出了一个 Name 类型的值:

Name{Forename: "Robert", Surname: "Hao"}

其中 Name 表示这个值的类型,紧随其后的就是由键值对表示的复合元素列表。

四、分隔符

分隔符用来分隔 Go 语言中其它词法元素, 包括小括号、中括号、大括号、小数点、逗号、分号、冒号、省略号。
在 Go 程序中,一行代表一个语句结束。每个语句不需要像 C 家族中的其它语言一样以分号结尾,因为这些工作都将由 Go 编译器自动完成。如果你打算将多个语句写在同一行,它们则必须使用分号人为区分,但在实际开发中我们并不鼓励这种做法。

五、操作符

操作符,也称 运算符 ,它是用于 数据运算 的符号。包括 算术运算符 关系运算符 逻辑运算符 位运算符 赋值运算符 其他运算符
算术运算符 (假定 A 值为 10,B 值为 20):

运算符 描述 实例
+ 相加 A + B 输出结果 30
- 相减 A - B 输出结果 -10
* 相乘 A * B 输出结果 200
/ 相除 B / A 输出结果 2
% 求余 B % A 输出结果 0
++ 自增 A++ 输出结果 11
-- 自减 A-- 输出结果 9

关系运算符 (假定 A 值为 10,B 值为 20):

运算符 描述 实例
== 检查两个值是否相等,如果相等返回 True。(A == B) 为 False
!=检查两个值是否不相等,如果不相等返回 True。(A != B) 为 True
>检查左边值是否大于右边值,如果是返回 True。(A > B) 为 False
<检查左边值是否小于右边值,如果是返回 True。(A < B) 为 True
>=检查左边值是否大于等于右边值,如果是返回 True。(A >= B) 为 False
<=检查左边值是否小于等于右边值,如果是返回 True。(A <= B) 为 True

逻辑运算符 (假定 A 值为 True,B 值为 False):

运算符 描述 实例
&& 逻辑 AND 运算符。如果两边的操作数都是 True,则条件 True。(A && B) 为 False
||逻辑 OR 运算符。如果两边的操作数有一个 True,则条件 True。(A || B) 为 True
!逻辑 NOT 运算符。如果条件为 True,则逻辑 NOT 条件 False。!(A && B) 为 True

位运算符 (假定 A 为 60,B 为 13,二进制为 0011 1100、0000 1101):

运算符 描述 实例
& 按位与。参与运算的两数各对应的二进位相与。(A & B) 结果为 12, 二进制为 0000 1100
|按位或。参与运算的两数各对应的二进位相或。(A | B) 结果为 61, 二进制为 0011 1101
^按位异或、按位取反。参与运算的两数各对应的二进位相异或、参与运算的数对应的二进位取反,(A ^ B) 结果为 49, 二进制为 0011 0001、(^ A) 结果为 195, 二进制为 1100 0011,
<<左移。左移 n 位就是乘以 2 的 n 次方。把 "<<" 左边的运算数的各二进位全部左移若干位,"<<" 右边的数指定移动的位数,高位丢弃,低位补 0。A << 2 结果为 240 ,二进制为 1111 0000
>>右移。右移 n 位就是除以 2 的 n 次方。把 ">>" 左边的运算数的各二进位全部右移若干位,">>" 右边的数指定移动的位数,高位补 0,低位丢弃。A >> 2 结果为 15 ,二进制为 0000 1111
&^按位清零。同 a &(^b), 将运算符左边数据相异的位保留、相同位清零,如果右侧是 0,则左侧数保持不变,如果右侧是 1,则左侧数一定清零。(A &^ B) 结果为 48,二进制为 0011 0000

赋值运算符

运算符 描述 实例
= 简单的赋值运算符,将一个表达式的值赋给一个左值 C = A + B 将 A + B 表达式结果赋值给 C
+= 相加后再赋值 C += A 等于 C = C + A
-= 相减后再赋值 C -= A 等于 C = C - A
*= 相乘后再赋值 C = A 等于 C = C A
/= 相除后再赋值 C /= A 等于 C = C / A
%= 求余后再赋值 C %= A 等于 C = C % A
<<= 左移后赋值 C <<= 2 等于 C = C << 2
>>= 右移后赋值 C >>= 2 等于 C = C >> 2
&= 按位与后赋值 C &= 2 等于 C = C & 2
^= 按位异或后赋值 C ^= 2 等于 C = C ^ 2
|= 按位或后赋值 C |= 2 等于 C = C | 2

其他运算符

运算符 描述 实例
& 返回变量存储地址 &a; 将给出变量的实际地址。
* 指针变量。*a; 是一个指针变量
<- 管道操作符。<-a; 从管道 a 中获取一个元素

运算符优先级
有些运算符拥有较高的优先级,二元运算符的运算方向均是从左至右。

优先级 运算符
7^ !
6* / % << >> & &^
5+ - | ^
4== != < <= >= >
3<-
2&&
1||

注意

  • 优先级值越大,表示优先级越高。
  • Go 语言中按位取反和按位异或的操作符都是 ^, 按位取反的优先级为 7,按位异或的优先级为 5
  • 双目运算符可以和等号复合成赋值运算符
  • Go 语言中大部分运算符的优先级和数学中是一样的,如果实在不清楚,可以加括号来临时提升优先级
  • Go 的自增、自减只有 a ++、a--,不存在 ++a、--a。
  • Go 的自增、自减只能作为表达式使用,而不能用于赋值语句,a = a++ 这是不允许的。
  • 相加运算符,也可以完成字符串的连接运算,例如 "hello" + "" +"world!"。