Go 语言运算符详解:从基础到实战

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!"

示例代码:

go 复制代码
package main

import "fmt"

func main() {
    a := 10
    b := 3

    fmt.Println("a + b =", a+b) // 13
    fmt.Println("a - b =", a-b) // 7
    fmt.Println("a * b =", a*b) // 30
    fmt.Println("a / b =", a/b) // 3 (整数除法)
    fmt.Println("a % b =", a%b) // 1

    a++ // a 变为 11
    fmt.Println("a++ =", a)
    b-- // b 变为 2
    fmt.Println("b-- =", b)

    // 字符串"加法"
    str1 := "Go"
    str2 := "Lang"
    fmt.Println(str1 + " " + str2) // Go Lang
}

3. 关系运算符(比较运算符)

关系运算符用于比较两个值,返回一个布尔值 (truefalse)。

运算符 描述 示例
== 等于 a == b
!= 不等于 a != b
> 大于 a > b
< 小于 a < b
>= 大于等于 a >= b
<= 小于等于 a <= b

示例代码:

go 复制代码
package main

import "fmt"

func main() {
    x := 5
    y := 10

    fmt.Println("x == y?", x == y) // false
    fmt.Println("x != y?", x != y) // true
    fmt.Println("x > y?", x > y)   // false
    fmt.Println("x < y?", x < y)   // true
    fmt.Println("x >= 5?", x >= 5) // true
    fmt.Println("y <= 10?", y <= 10) // true
}

4. 逻辑运算符

逻辑运算符用于组合或反转布尔条件。

运算符 描述 示例
&& 逻辑与 (AND)。两边都为 true 时结果为 true a && b
` `
! 逻辑非 (NOT)。反转布尔值。 !a

Go 中的逻辑运算符支持短路求值

  • 对于 &&,如果左边表达式为 false,则右边表达式不会被计算。
  • 对于 ||,如果左边表达式为 true,则右边表达式不会被计算。

示例代码:

go 复制代码
package main

import "fmt"

func main() {
    a := true
    b := false

    fmt.Println("a && b =", a && b) // false
    fmt.Println("a || b =", a || b) // true
    fmt.Println("!a =", !a)         // false
    fmt.Println("!b =", !b)         // true

    // 短路求值示例
    var count int
    // 由于 false && ...,increment() 永远不会被调用
    if false && increment(&count) {
        // 不会执行
    }
    fmt.Println("Count after false &&:", count) // 0

    // 由于 true || ...,increment() 永远不会被调用
    if true || increment(&count) {
        // 会执行
    }
    fmt.Println("Count after true ||:", count) // 0 (仍然为0)
}

func increment(c *int) bool {
    *c++
    return true
}

5. 位运算符

位运算符在整数的二进制位级别进行操作。

运算符 描述 示例
& 按位与 (AND)。两位都为1时结果为1。 a & b
` ` 按位或 (OR)。至少一位为1时结果为1。
^ 按位异或 (XOR)。两位不同时结果为1。 a ^ b
&^ 位清空 (AND NOT)。将 b 中为1的位,在 a 中对应位清零。 a &^ b
<< 左移。左操作数按位左移右操作数指定的位数。 a << n
>> 右移。左操作数按位右移右操作数指定的位数。 a >> n

示例代码:

go 复制代码
package main

import "fmt"

func main() {
    var a uint = 60 // 二进制: 0011 1100
    var b uint = 13 // 二进制: 0000 1101

    fmt.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

示例代码:

go 复制代码
package main

import "fmt"

func main() {
    var a int = 10
    a += 5 // a = 15
    fmt.Println("a += 5 ->", a)

    a -= 3 // a = 12
    fmt.Println("a -= 3 ->", a)

    a *= 2 // a = 24
    fmt.Println("a *= 2 ->", a)

    a /= 4 // a = 6
    fmt.Println("a /= 4 ->", a)

    a %= 4 // a = 2
    fmt.Println("a %= 4 ->", a)

    var b uint = 0b1111 // 15
    b &= 0b1010 // b = 10 (0b1010)
    fmt.Printf("b &= 0b1010 -> %b (%d)\n", b, b)
}

7. 其他运算符

运算符 描述 示例
& 取地址运算符。返回变量的内存地址。 &a
* 指针解引用运算符。返回指针指向地址的值。 *ptr
<- 通道运算符。用于向通道发送或从通道接收值。 ch <- v (发送), v := <-ch (接收)

示例代码:

go 复制代码
package main

import "fmt"

func main() {
    // 1. 取地址与解引用
    x := 42
    ptr := &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(chan int, 1) // 创建一个缓冲大小为1的通道
    ch <- 99                // 向通道发送值 99
    received := <-ch        // 从通道接收值
    fmt.Println("从通道接收到的值:", received)
}

8. 运算符优先级

当表达式中包含多个运算符时,运算顺序由运算符的优先级决定。优先级高的运算符先计算。如果优先级相同,则按从左到右的顺序计算(赋值运算符除外,它是从右向左结合)。

下表列出了 Go 运算符的优先级,从高到低排列:

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

注意:

  • 可以使用括号 () 来显式地改变运算顺序,括号内的表达式总是最先计算。
  • 赋值运算符(如 =+=)的优先级最低,且是右结合的。

示例:

go 复制代码
result := 5 + 3*2 // 先算 3*2=6,再算 5+6=11
fmt.Println(result) // 11

result2 := (5 + 3) * 2 // 先算括号 5+3=8,再算 8*2=16
fmt.Println(result2) // 16

a, b := 1, 2
a += b * 3 // 等价于 a = a + (b * 3) -> a = 1 + 6 = 7
fmt.Println(a) // 7

9. 总结

Go 语言的运算符设计简洁而强大,遵循了 C 语言家族的传统,同时去除了一些容易导致错误的特性(如将 ++/-- 限制为语句)。理解并熟练运用这些运算符是进行 Go 编程的基础。记住以下几点关键区别:

  1. ++/-- 是语句,不能参与表达式运算。
  2. 字符串连接使用 + 运算符。
  3. 逻辑运算符 &&|| 支持短路求值。
  4. Go 特有的 &^(位清空)运算符非常实用。
  5. 使用括号来明确复杂表达式的计算顺序。

建议读者在 IDE 或编辑器中多练习这些运算符的组合使用,以加深理解。

相关推荐
XovH1 小时前
MySQL 系列:第2篇 库和表,一切的容器
后端
是苏浙1 小时前
Java实现链表2
java·开发语言·数据结构
笨鸟飞不快1 小时前
当定时任务涨到 180+,我们为什么从 Elastic Job 迁到了 XXL-JOB
后端
Kir1to1 小时前
分布式锁基础与三种实现方式对比
后端
MariaH1 小时前
Web服务器开发
后端
程序边界1 小时前
凌晨三点批量掉授权,我花了四小时才搞明白LAC心跳链路是怎么算的
后端
叫我:松哥1 小时前
基于Flask的在线考试刷题系统设计与实现,集智能练习、过程追踪、深度分析与个性化引导
数据库·人工智能·后端·python·flask·boostrap
AI人工智能_电脑小能手1 小时前
【大白话说Java面试题 第106题】【并发篇】第6题:synchronized 锁的锁对象可以是什么?
java·后端·面试
Rain5091 小时前
2.3. 安全配置:环境变量与 API 密钥管理
前端·人工智能·后端·安全·ai·node.js·ai编程