1. 引言
运算符是任何编程语言的基础构建块,用于对变量和值执行操作。Go 语言提供了一套丰富且清晰的运算符,涵盖了算术、比较、逻辑、位运算、赋值等多个方面。掌握这些运算符是编写高效、可读 Go 代码的关键第一步。本文将系统性地介绍 Go 语言中的所有运算符,并通过代码示例帮助你深入理解其用法和注意事项。
2. 算术运算符
算术运算符用于执行基本的数学运算。
| 运算符 | 描述 | 示例 |
|---|---|---|
+ | 加法 | a + b |
- | 减法 | a - b |
* | 乘法 | a * b |
/ | 除法 | a / b |
% | 取模(求余) | a % b |
++ | 自增 | a++ |
-- | 自减 | a-- |
重要说明:
++和--在 Go 中是语句,而非表达式。这意味着它们不能出现在赋值语句的右侧,也不能与其他运算符混合使用。例如,b = a++或if a++ > 0在 Go 中是非法的。- Go 语言没有
+运算符用于字符串连接,而是使用+运算符。例如:"Hello, " + "World!"。
示例代码:
packagemainimport"fmt"funcmain(){a:=10b:=3fmt.Println("a + b =",a+b)// 13fmt.Println("a - b =",a-b)// 7fmt.Println("a * b =",a*b)// 30fmt.Println("a / b =",a/b)// 3 (整数除法)fmt.Println("a % b =",a%b)// 1a++// a 变为 11fmt.Println("a++ =",a)b--// b 变为 2fmt.Println("b-- =",b)// 字符串“加法”str1:="Go"str2:="Lang"fmt.Println(str1+" "+str2)// Go Lang}3. 关系运算符(比较运算符)
关系运算符用于比较两个值,返回一个布尔值 (true或false)。
| 运算符 | 描述 | 示例 |
|---|---|---|
== | 等于 | a == b |
!= | 不等于 | a != b |
> | 大于 | a > b |
< | 小于 | a < b |
>= | 大于等于 | a >= b |
<= | 小于等于 | a <= b |
示例代码:
packagemainimport"fmt"funcmain(){x:=5y:=10fmt.Println("x == y?",x==y)// falsefmt.Println("x != y?",x!=y)// truefmt.Println("x > y?",x>y)// falsefmt.Println("x < y?",x<y)// truefmt.Println("x >= 5?",x>=5)// truefmt.Println("y <= 10?",y<=10)// true}4. 逻辑运算符
逻辑运算符用于组合或反转布尔条件。
| 运算符 | 描述 | 示例 |
|---|---|---|
&& | 逻辑与 (AND)。两边都为true时结果为true。 | a && b |
| ` | ` | |
! | 逻辑非 (NOT)。反转布尔值。 | !a |
Go 中的逻辑运算符支持短路求值:
- 对于
&&,如果左边表达式为false,则右边表达式不会被计算。 - 对于
||,如果左边表达式为true,则右边表达式不会被计算。
示例代码:
packagemainimport"fmt"funcmain(){a:=trueb:=falsefmt.Println("a && b =",a&&b)// falsefmt.Println("a || b =",a||b)// truefmt.Println("!a =",!a)// falsefmt.Println("!b =",!b)// true// 短路求值示例varcountint// 由于 false && ...,increment() 永远不会被调用iffalse&&increment(&count){// 不会执行}fmt.Println("Count after false &&:",count)// 0// 由于 true || ...,increment() 永远不会被调用iftrue||increment(&count){// 会执行}fmt.Println("Count after true ||:",count)// 0 (仍然为0)}funcincrement(c*int)bool{*c++returntrue}5. 位运算符
位运算符在整数的二进制位级别进行操作。
| 运算符 | 描述 | 示例 |
|---|---|---|
& | 按位与 (AND)。两位都为1时结果为1。 | a & b |
| ` | ` | 按位或 (OR)。至少一位为1时结果为1。 |
^ | 按位异或 (XOR)。两位不同时结果为1。 | a ^ b |
&^ | 位清空 (AND NOT)。将b中为1的位,在a中对应位清零。 | a &^ b |
<< | 左移。左操作数按位左移右操作数指定的位数。 | a << n |
>> | 右移。左操作数按位右移右操作数指定的位数。 | a >> n |
示例代码:
packagemainimport"fmt"funcmain(){varauint=60// 二进制: 0011 1100varbuint=13// 二进制: 0000 1101fmt.Printf("a = %d, 二进制: %08b\n",a,a)fmt.Printf("b = %d, 二进制: %08b\n",b,b)fmt.Printf("a & b = %d, 二进制: %08b\n",a&b,a&b)// 12 (0000 1100)fmt.Printf("a | b = %d, 二进制: %08b\n",a|b,a|b)// 61 (0011 1101)fmt.Printf("a ^ b = %d, 二进制: %08b\n",a^b,a^b)// 49 (0011 0001)fmt.Printf("a &^ b = %d, 二进制: %08b\n",a&^b,a&^b)// 48 (0011 0000) 清空b中为1的位fmt.Printf("a << 2 = %d, 二进制: %08b\n",a<<2,a<<2)// 240 (1111 0000)fmt.Printf("a >> 2 = %d, 二进制: %08b\n",a>>2,a>>2)// 15 (0000 1111)}6. 赋值运算符
赋值运算符用于为变量赋值。
| 运算符 | 示例 | 等价于 |
|---|---|---|
= | a = 5 | a = 5 |
+= | a += 3 | a = a + 3 |
-= | a -= 3 | a = a - 3 |
*= | a *= 3 | a = a * 3 |
/= | a /= 3 | a = a / 3 |
%= | a %= 3 | a = a % 3 |
&= | a &= 3 | a = a & 3 |
| ` | =` | `a |
^= | a ^= 3 | a = a ^ 3 |
&^= | a &^= 3 | a = a &^ 3 |
<<= | a <<= 3 | a = a << 3 |
>>= | a >>= 3 | a = a >> 3 |
示例代码:
packagemainimport"fmt"funcmain(){varaint=10a+=5// a = 15fmt.Println("a += 5 ->",a)a-=3// a = 12fmt.Println("a -= 3 ->",a)a*=2// a = 24fmt.Println("a *= 2 ->",a)a/=4// a = 6fmt.Println("a /= 4 ->",a)a%=4// a = 2fmt.Println("a %= 4 ->",a)varbuint=0b1111// 15b&=0b1010// b = 10 (0b1010)fmt.Printf("b &= 0b1010 -> %b (%d)\n",b,b)}7. 其他运算符
| 运算符 | 描述 | 示例 |
|---|---|---|
& | 取地址运算符。返回变量的内存地址。 | &a |
* | 指针解引用运算符。返回指针指向地址的值。 | *ptr |
<- | 通道运算符。用于向通道发送或从通道接收值。 | ch <- v(发送),v := <-ch(接收) |
示例代码:
packagemainimport"fmt"funcmain(){// 1. 取地址与解引用x:=42ptr:=&x// ptr 是一个指向 x 的指针fmt.Println("x 的值:",x)fmt.Println("x 的地址:",ptr)fmt.Println("通过指针访问 x 的值:",*ptr)*ptr=100// 通过指针修改 x 的值fmt.Println("修改后 x 的值:",x)// 2. 通道运算符 (简单示例)ch:=make(chanint,1)// 创建一个缓冲大小为1的通道ch<-99// 向通道发送值 99received:=<-ch// 从通道接收值fmt.Println("从通道接收到的值:",received)}8. 运算符优先级
当表达式中包含多个运算符时,运算顺序由运算符的优先级决定。优先级高的运算符先计算。如果优先级相同,则按从左到右的顺序计算(赋值运算符除外,它是从右向左结合)。
下表列出了 Go 运算符的优先级,从高到低排列:
| 优先级 | 运算符 |
|---|---|
| 5 | */%<<>>&&^ |
| 4 | +-` |
| 3 | ==!=<<=>>= |
| 2 | && |
| 1 | ` |
注意:
- 可以使用括号
()来显式地改变运算顺序,括号内的表达式总是最先计算。 - 赋值运算符(如
=、+=)的优先级最低,且是右结合的。
示例:
result:=5+3*2// 先算 3*2=6,再算 5+6=11fmt.Println(result)// 11result2:=(5+3)*2// 先算括号 5+3=8,再算 8*2=16fmt.Println(result2)// 16a,b:=1,2a+=b*3// 等价于 a = a + (b * 3) -> a = 1 + 6 = 7fmt.Println(a)// 79. 总结
Go 语言的运算符设计简洁而强大,遵循了 C 语言家族的传统,同时去除了一些容易导致错误的特性(如将++/--限制为语句)。理解并熟练运用这些运算符是进行 Go 编程的基础。记住以下几点关键区别:
++/--是语句,不能参与表达式运算。- 字符串连接使用
+运算符。 - 逻辑运算符
&&和||支持短路求值。 - Go 特有的
&^(位清空)运算符非常实用。 - 使用括号来明确复杂表达式的计算顺序。
建议读者在 IDE 或编辑器中多练习这些运算符的组合使用,以加深理解。