Skip to content

Go 运算符

运算符是一个符号,它告诉编译器执行特定的数学、逻辑或位操作。Go 语言提供了丰富的内置运算符,它们按以下类别划分:

  • 算术运算符
  • 关系运算符
  • 逻辑运算符
  • 位运算符
  • 赋值运算符
  • 其他运算符(如取地址 & 和解引用 *)

本教程将引导您了解 Go 语言中的各类运算符。

这些运算符执行数学计算。假设变量 a 的值为 10,变量 b 的值为 20:

示例代码:

package main
import "fmt"
func main() {
a := 10
b := 20
var result int
result = a + b
fmt.Printf("a + b = %d\n", result) // 输出: a + b = 30
result = a - b
fmt.Printf("a - b = %d\n", result) // 输出: a - b = -10
result = a * b
fmt.Printf("a * b = %d\n", result) // 输出: a * b = 200
result = b / a
fmt.Printf("b / a = %d\n", result) // 输出: b / a = 2 (整型除法)
result = b % a
fmt.Printf("b %% a = %d\n", result) // 输出: b % a = 0
// Go 中 ++/-- 是语句,不是表达式。
a++ // a 自增 1 (a 变为 11)
fmt.Printf("After a++, a = %d\n", a) // 输出: After a++, a = 11
a-- // a 自减 1 (a 变为 10)
fmt.Printf("After a--, a = %d\n", a) // 输出: After a--, a = 10
}
运算符描述示例 (a=10, b=20)
+加法:将两个操作数相加。a + b 结果为 30
-减法:从第一个操作数中减去第二个操作数。a - b 结果为 -10
*乘法:将两个操作数相乘。a * b 结果为 200
/除法:用分子除以分母。如果两个操作数都是整数,结果为整数。b / a 结果为 2
%取模:返回整数除法的余数。b % a 结果为 0
++自增语句:将整数值增加一。不是表达式。a++ 将 a 变为 11
—自减语句:将整数值减少一。不是表达式。a-- 将 a 变为 9 (如果初始 a=10)

注意:Go 中的 ++ 和 -- 是语句,而不是表达式。您不能写 c := a++ 这样的代码。

这些运算符比较两个操作数并返回布尔值(true 或 false)。假设 a 的值为 10,b 的值为 20:

示例代码:

package main
import "fmt"
func main() {
a := 10
b := 20
fmt.Printf("a == b: %t\n", a == b) // 输出: a == b: false
fmt.Printf("a != b: %t\n", a != b) // 输出: a != b: true
fmt.Printf("a > b: %t\n", a > b) // 输出: a > b: false
fmt.Printf("a < b: %t\n", a < b) // 输出: a < b: true
fmt.Printf("a >= b: %t\n", a >= b) // 输出: a >= b: false
fmt.Printf("a <= b: %t\n", a <= b) // 输出: a <= b: true
}
运算符描述示例 (a=10, b=20)
==检查两个操作数的值是否相等。如果相等,则返回 true。(a == b) 为 false。
!=检查两个操作数的值是否不相等。如果不相等,则返回 true。(a != b) 为 true。
>检查左操作数的值是否大于右操作数的值。(a > b) 为 false。
<检查左操作数的值是否小于右操作数的值。(a < b) 为 true。
>=检查左操作数的值是否大于或等于右操作数的值。(a >= b) 为 false。
<=检查左操作数的值是否小于或等于右操作数的值。(a <= b) 为 true。

这些运算符作用于布尔操作数。假设 a 为 true,b 为 false:

示例代码:

package main
import "fmt"
func main() {
a := true
b := false
fmt.Printf("a && b: %t\n", a && b) // 输出: a && b: false
fmt.Printf("a || b: %t\n", a || b) // 输出: a || b: true
fmt.Printf("!a: %t\n", !a) // 输出: !a: false
fmt.Printf("!(a && b): %t\n", !(a && b)) // 输出: !(a && b): true
}
运算符描述示例 (a=true, b=false)
&&逻辑 AND。如果两个操作数都为 true,则返回 true。(a && b) 为 false。
||逻辑 OR。如果至少一个操作数为 true,则返回 true。(a || b) 为 true。
!逻辑 NOT。反转操作数的逻辑状态。如果 a 为 true,则 !a 为 false。!(a && b) 为 true。

位运算符在二进制级别对整型操作数执行操作。考虑 AND (&)、OR (|) 和 XOR (^) 的真值表:

pqp & qp | qp ^ q
00000
01011
11110
10011

假设 a = 60 (二进制 0011 1100) 和 b = 13 (二进制 0000 1101):

a = 0011 1100
b = 0000 1101
-----------------
a & b = 0000 1100 (12)
a | b = 0011 1101 (61)
a ^ b = 0011 0001 (49)
a &^ b = 0011 0000 (48) (Bit Clear)

Go 中的位运算符 NOT (^) 实际上是 XOR。要执行按位补码操作(类似于 C 语言的 ~),您需要与掩码进行 XOR(例如,对于 32 位整数,m = a ^ 0xFFFFFFFF)。对于无符号整数,如果上下文暗示了位宽,通常可以使用 ^a,或者使用 math.MaxUintXX。

示例代码:

package main
import "fmt"
func main() {
var a uint = 60 // 0011 1100
var b uint = 13 // 0000 1101
var result uint
result = a & b
fmt.Printf("a & b = %d (binary %08b)\n", result, result) // 输出: a & b = 12 (二进制 00001100)
result = a | b
fmt.Printf("a | b = %d (binary %08b)\n", result, result) // 输出: a | b = 61 (二进制 00111101)
result = a ^ b
fmt.Printf("a ^ b = %d (binary %08b)\n", result, result) // 输出: a ^ b = 49 (二进制 00110001)
result = a << 2
fmt.Printf("a << 2 = %d (binary %08b)\n", result, result) // 输出: a << 2 = 240 (二进制 11110000)
result = a >> 2
fmt.Printf("a >> 2 = %d (binary %08b)\n", result, result) // 输出: a >> 2 = 15 (二进制 00001111)
// 位清零 (AND NOT)
result = a &^ b // 清除 'a' 中在 'b' 中设置的位
fmt.Printf("a &^ b = %d (binary %08b)\n", result, result) // 输出: a &^ b = 48 (二进制 00110000)
}
运算符描述示例 (a=60, b=13, 无符号)
&按位 AND:如果位在两个操作数中都存在,则将该位设置为 1。a & b 结果为 12 (0000 1100)
|按位 OR:如果位在任一操作数中存在,则将该位设置为 1。a | b 结果为 61 (0011 1101)
^按位 XOR:如果位仅在一个操作数中设置(不同),则将该位设置为 1。a ^ b 结果为 49 (0011 0001)
<<左移:将左操作数的位向左移动由右操作数指定的位数。用零填充空位。a << 2 结果为 240 (1111 0000)
>>右移:将左操作数的位向右移动由右操作数指定的位数。行为取决于是有符号还是无符号类型(算术移位 vs 逻辑移位)。a >> 2 结果为 15 (对于无符号 a 是 0000 1111)
&^位清零 (AND NOT):清除左操作数中在右操作数中设置的位(相当于 a & (^b))。a &^ b 结果为 48 (0011 0000)

这些运算符用于给变量赋值,通常会将算术或位操作与赋值结合起来。

示例代码:

package main
import "fmt"
func main() {
a := 10
c := 5
c += a // c = c + a = 5 + 10 = 15
fmt.Printf("c += a -> c = %d\n", c)
c = 5 // 重置 c
c -= a // c = c - a = 5 - 10 = -5
fmt.Printf("c -= a -> c = %d\n", c)
c = 5 // 重置 c
c *= a // c = c * a = 5 * 10 = 50
fmt.Printf("c *= a -> c = %d\n", c)
c = 50 // 重置 c
c /= a // c = c / a = 50 / 10 = 5
fmt.Printf("c /= a -> c = %d\n", c)
c = 51 // 重置 c
c %= a // c = c % a = 51 % 10 = 1
fmt.Printf("c %%= a -> c = %d\n", c)
// 位赋值运算符的类似示例 (<<=, >>=, &=, ^=, |=, &^=)
d := uint(60) // 位操作使用 uint 类型
d <<= 2 // d = d << 2
fmt.Printf("d <<= 2 -> d = %d\n", d)
}
运算符描述示例
=简单赋值:将右侧的值赋给左侧操作数。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。
&=按位 AND 赋值。c &= 2 等同于 c = c & 2。
^=按位 XOR 赋值。c ^= 2 等同于 c = c ^ 2。
|=按位 OR 赋值。c |= 2 等同于 c = c | 2。
&^=位清零赋值。c &^= 2 等同于 c = c &^ 2。

Go 语言包含与内存地址和指针相关的运算符:

示例代码:

package main
import "fmt"
func main() {
a := 100
var ptr *int // 声明一个指向整数的指针
ptr = &a // 将 'a' 的内存地址赋给指针变量 'ptr'
fmt.Printf("Address of a: %p\n", &a) // 输出: Address of a: 0x... (实际地址)
fmt.Printf("Value stored in ptr: %p\n", ptr) // 输出: Value stored in ptr: 0x... (相同的地址)
// 解引用指针以获取值
fmt.Printf("Value pointed to by ptr (*ptr): %d\n", *ptr) // 输出: Value pointed to by ptr (*ptr): 100
}
运算符描述示例
&取地址运算符:返回变量的内存地址。&a 获取变量 a 的实际内存地址。
*解引用运算符(与指针一起使用时):访问指针所持有的内存地址处存储的值。*ptr 获取 ptr 指向的地址处存储的值。

注意:Go 语言不像 C 或 Java 那样有三元运算符(? :)。您必须使用标准的 if-else 语句。

sizeof 的概念由 unsafe 包中的 unsafe.Sizeof 函数处理,但除非处理底层操作或需要互操作性,否则通常不建议使用它。

运算符优先级定义了表达式中操作执行的顺序。优先级高的运算符会先被求值。例如,乘法的优先级高于加法。

示例:x := 7 + 3 * 2。在这里,由于 * 的优先级较高,先计算 3 * 2 (结果为 6),然后计算 7 + 6。因此,x 的值是 13,而不是 20。

同一优先级级别的运算符通常从左到右求值(请查看结合性)。可以使用括号 () 来覆盖优先级。

Go 运算符优先级(从高到低):

类别运算符结合性
一元运算符+ - ! ^ * & <- (一元运算符、指针操作、通道接收)无 (最高)
乘法/位移/按位* / % << >> & &^从左到右
加法/按位+ - | ^从左到右
比较== != < <= > >=从左到右
逻辑 AND&&从左到右
逻辑 OR||从左到右

注意:赋值操作在对右侧表达式求值后进行。上面的优先级表是简化的;要获取完整详情,请参考官方 Go 语言规范。