Appearance
The Go Programming Language - 运算符及流程控制语句
1. 运算符
关于
++、--的一些特殊说明:
++/--只允许放在变量名后面,所以++i是非法的;i++是一个语句而不是表达式,所以j = i++是非法的;
1.1. 优先级
从左至右,从上到下代表优先级由高到低。
| 优先级 | 分类 | 运算符 | 结合性 |
|---|---|---|---|
| 14 | 后缀运算符 | () [] -> | 从左到右 |
| 13 | 单目运算符 | ! ^(取反) *(指针) &(地址) ++ -- +(正号) -(负号) | 从右到左 |
| 12 | 乘法/除法/取余 | *(乘号) / % | 从左到右 |
| 11 | 加法/减法 | + - | 从左到右 |
| 10 | 位移运算符 | << >> | 从左到右 |
| 9 | 关系运算符 | < <= > >= | 从左到右 |
| 8 | 相等/不等 | == != | 从左到右 |
| 7 | 按位与 | & | 从左到右 |
| 6 | 按位异或 | ^ | 从左到右 |
| 5 | 按位或 | | | 从左到右 |
| 4 | 逻辑与 | && | 从左到右 |
| 3 | 逻辑或 | || | 从左到右 |
| 2 | 赋值运算符 | = += -= *= /= %= >= <<= &= ^= |= | 从右到左 |
| 1 | 逗号运算符 | , | 从左到右 |
Note
无符号数的右移运算是用
0填充左边空缺的bit位,但是有符号数的右移运算会用符号位的值填充左边空缺的bit位。因为这个原因,最好用无符号运算,这样你可以将整数完全当作一个bit位模式处理。
1.2. 元组赋值
元组赋值是另一种形式的赋值语句,它允许同时更新多个变量的值。在赋值之前,赋值语句右边的所有表达式将会先进行求值,然后再统一更新左边对应变量的值。这对于处理有些同时出现在元组赋值语句左右两边的变量很有帮助,例如我们可以这样交换两个变量的值:
Go
x, y = y, x
a[i], a[j] = a[j], a[i]1
2
3
2
3
2. 流程控制语句
2.1. if
EBNF
IfStmt = "if" [ SimpleStmt ";" ] Expression Block [ "else" ( IfStmt | Block ) ]Go
if x := f(); x < y {
return x
} else if x > z {
return z
} else {
return y
}
// "x" not available here1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
控制台输出:
Text
ok2.2. switch
EBNF
SwitchStmt = ExprSwitchStmt | TypeSwitchStmt
ExprSwitchStmt = "switch" [ SimpleStmt ";" ] [ Expression ] "{" { ( "case" ExpressionList | "default" ) ":" StatementList } "}"
TypeSwitchStmt = "switch" [ SimpleStmt ";" ] [ identifier ":=" ] PrimaryExpr ".(type) {" { ( "case" TypeList | "default" ) ":" StatementList } "}"
TypeList = Type { "," Type }switch后的初始化语句(SimpleStmt)、条件语句(Expression)均可省略,省略条件语句时,默认条件为true。case后面带是表达式(Expression),也就是说case后面可以是常量、变量、一小段代码甚至函数等等。case后面也可以带多个表达式(ExpressionList)。case按从上到下从左到右的顺序进行求值,直到找到匹配的项。case后面默认带break,如需穿透到下一个case则只需在当前case末尾加fallthrough关键字即可。
拓展链接:类型 switch
2.3. select
2.4. for
EBNF
ForStmt = "for" [ Condition | ForClause | RangeClause ] Block
ForClause = [ InitStmt ] ";" [ Condition ] ";" [ PostStmt ]
RangeClause = [ ExpressionList "=" | IdentifierList ":=" ] "range" ExpressionNote
Go语言中的循环语句只支持for关键字,不支持while和do-while结构。
2.5. break
EBNF
BreakStmt = "break" [ Label ]如果在 break 后面有标签,那么跳转标签的位置必须在 for、switch、select 前
2.6. continue
EBNF
ContinueStmt = "continue" [ Label ]如果在 continue 后面有标签,那么跳转标签的位置必须在 for 前
2.7. goto
GotoStmt = "goto" Label
2.8. defer
参考:Deferred 函数