Skip to content

Go 语言运算符

运算符是用于执行特定运算的符号。Go 语言提供了丰富的运算符,包括算术、比较、逻辑、位运算、赋值等运算符。本章将详细介绍各种运算符的使用方法和应用场景。

🧮 算术运算符

基本算术运算

go
package main

import "fmt"

func main() {
    a, b := 15, 4
    
    fmt.Printf("a = %d, b = %d\n", a, b)
    fmt.Printf("加法: %d + %d = %d\n", a, b, a+b)     // 19
    fmt.Printf("减法: %d - %d = %d\n", a, b, a-b)     // 11
    fmt.Printf("乘法: %d * %d = %d\n", a, b, a*b)     // 60
    fmt.Printf("除法: %d / %d = %d\n", a, b, a/b)     // 3 (整数除法)
    fmt.Printf("取余: %d %% %d = %d\n", a, b, a%b)    // 3
    
    // 浮点数运算
    x, y := 15.0, 4.0
    fmt.Printf("\n浮点数运算:\n")
    fmt.Printf("%.1f / %.1f = %.2f\n", x, y, x/y)    // 3.75
    
    // 一元运算符
    fmt.Printf("\n一元运算符:\n")
    fmt.Printf("+a = %d\n", +a)    // 15 (正号)
    fmt.Printf("-a = %d\n", -a)    // -15 (负号)
}

整数除法和取余

go
func main() {
    // 整数除法(截断除法)
    fmt.Println("整数除法:")
    fmt.Printf("7 / 3 = %d\n", 7/3)      // 2
    fmt.Printf("7 / -3 = %d\n", 7/-3)    // -2
    fmt.Printf("-7 / 3 = %d\n", -7/3)    // -2
    fmt.Printf("-7 / -3 = %d\n", -7/-3)  // 2
    
    // 取余运算
    fmt.Println("\n取余运算:")
    fmt.Printf("7 %% 3 = %d\n", 7%3)     // 1
    fmt.Printf("7 %% -3 = %d\n", 7%-3)   // 1
    fmt.Printf("-7 %% 3 = %d\n", -7%3)   // -1
    fmt.Printf("-7 %% -3 = %d\n", -7%-3) // -1
    
    // 应用:判断奇偶数
    numbers := []int{1, 2, 3, 4, 5, 6}
    for _, num := range numbers {
        if num%2 == 0 {
            fmt.Printf("%d 是偶数\n", num)
        } else {
            fmt.Printf("%d 是奇数\n", num)
        }
    }
}

递增和递减运算符

go
func main() {
    // 后置递增递减(Go 只有后置形式)
    i := 5
    fmt.Printf("初始值: i = %d\n", i)
    
    i++  // 等价于 i = i + 1
    fmt.Printf("i++ 后: i = %d\n", i)  // 6
    
    i--  // 等价于 i = i - 1
    fmt.Printf("i-- 后: i = %d\n", i)  // 5
    
    // 注意:++ 和 -- 是语句,不是表达式
    // x := i++  // 错误!不能这样使用
    // y := ++i  // 错误!Go 没有前置递增
    
    // 正确的用法
    j := i
    i++
    fmt.Printf("j = %d, i = %d\n", j, i)
    
    // 在循环中的常见用法
    fmt.Println("计数循环:")
    for count := 0; count < 5; count++ {
        fmt.Printf("计数: %d\n", count)
    }
}

⚖️ 比较运算符

基本比较运算

go
func main() {
    a, b := 10, 20
    
    fmt.Printf("a = %d, b = %d\n", a, b)
    fmt.Printf("a == b: %t\n", a == b)  // false (等于)
    fmt.Printf("a != b: %t\n", a != b)  // true  (不等于)
    fmt.Printf("a < b:  %t\n", a < b)   // true  (小于)
    fmt.Printf("a <= b: %t\n", a <= b)  // true  (小于等于)
    fmt.Printf("a > b:  %t\n", a > b)   // false (大于)
    fmt.Printf("a >= b: %t\n", a >= b)  // false (大于等于)
    
    // 字符串比较(字典序)
    str1, str2 := "apple", "banana"
    fmt.Printf("\n字符串比较:\n")
    fmt.Printf("\"%s\" < \"%s\": %t\n", str1, str2, str1 < str2)
    fmt.Printf("\"%s\" == \"%s\": %t\n", str1, str1, str1 == str1)
}

不同类型的比较

go
import "math"

func main() {
    // 浮点数比较需要注意精度问题
    f1 := 0.1 + 0.2
    f2 := 0.3
    
    fmt.Printf("0.1 + 0.2 = %.17f\n", f1)
    fmt.Printf("0.3 = %.17f\n", f2)
    fmt.Printf("f1 == f2: %t\n", f1 == f2)  // false!
    
    // 浮点数比较的正确方法
    epsilon := 1e-9
    isEqual := math.Abs(f1-f2) < epsilon
    fmt.Printf("使用精度比较: %t\n", isEqual)  // true
    
    // 特殊浮点值
    fmt.Printf("\n特殊浮点值比较:\n")
    fmt.Printf("NaN == NaN: %t\n", math.NaN() == math.NaN())  // false
    fmt.Printf("Inf == Inf: %t\n", math.Inf(1) == math.Inf(1))  // true
    
    // 布尔值比较
    fmt.Printf("\n布尔值比较:\n")
    fmt.Printf("true == true: %t\n", true == true)    // true
    fmt.Printf("true != false: %t\n", true != false)  // true
}

🧠 逻辑运算符

基本逻辑运算

go
func main() {
    a, b := true, false
    
    fmt.Printf("a = %t, b = %t\n", a, b)
    fmt.Printf("a && b: %t\n", a && b)  // false (逻辑与)
    fmt.Printf("a || b: %t\n", a || b)  // true  (逻辑或)
    fmt.Printf("!a: %t\n", !a)          // false (逻辑非)
    fmt.Printf("!b: %t\n", !b)          // true  (逻辑非)
    
    // 复合逻辑表达式
    x, y, z := true, false, true
    result1 := x && y || z      // (x && y) || z = false || true = true
    result2 := x && (y || z)    // x && (y || z) = true && true = true
    
    fmt.Printf("\n复合表达式:\n")
    fmt.Printf("x && y || z: %t\n", result1)
    fmt.Printf("x && (y || z): %t\n", result2)
}

短路求值

go
func main() {
    // 逻辑与的短路求值
    fmt.Println("逻辑与短路求值:")
    if false && expensiveFunction() {
        fmt.Println("不会执行")
    }
    
    // 逻辑或的短路求值
    fmt.Println("逻辑或短路求值:")
    if true || expensiveFunction() {
        fmt.Println("会执行,但expensiveFunction不会被调用")
    }
    
    // 实际应用:安全检查
    var ptr *int
    if ptr != nil && *ptr > 0 {
        fmt.Println("指针有效且值为正")
    } else {
        fmt.Println("指针为空或值不为正")
    }
}

func expensiveFunction() bool {
    fmt.Println("昂贵的函数被调用了")
    return true
}

🔢 位运算符

基本位运算

go
func main() {
    a, b := uint8(60), uint8(13)  // 60 = 0011 1100, 13 = 0000 1101
    
    fmt.Printf("a = %d (二进制: %08b)\n", a, a)
    fmt.Printf("b = %d (二进制: %08b)\n", b, b)
    
    fmt.Printf("\n位运算结果:\n")
    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 = %d (二进制: %08b)\n", ^a, ^a)        // 按位取反: 195 = 1100 0011
    
    // 位移运算
    fmt.Printf("\n位移运算:\n")
    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
}

位运算的应用

权限管理

go
func main() {
    // 使用位标志表示权限
    const (
        PermissionRead   = 1 << iota  // 1 = 0001
        PermissionWrite               // 2 = 0010
        PermissionExecute             // 4 = 0100
        PermissionDelete              // 8 = 1000
    )
    
    // 设置权限
    userPermissions := PermissionRead | PermissionWrite  // 3 = 0011
    
    fmt.Printf("用户权限: %d (二进制: %04b)\n", userPermissions, userPermissions)
    
    // 检查权限
    hasRead := userPermissions&PermissionRead != 0
    hasWrite := userPermissions&PermissionWrite != 0
    hasExecute := userPermissions&PermissionExecute != 0
    hasDelete := userPermissions&PermissionDelete != 0
    
    fmt.Printf("读权限: %t\n", hasRead)
    fmt.Printf("写权限: %t\n", hasWrite)
    fmt.Printf("执行权限: %t\n", hasExecute)
    fmt.Printf("删除权限: %t\n", hasDelete)
    
    // 添加权限
    userPermissions |= PermissionExecute
    fmt.Printf("添加执行权限后: %d (二进制: %04b)\n", userPermissions, userPermissions)
    
    // 移除权限
    userPermissions &^= PermissionWrite  // 位清除运算符
    fmt.Printf("移除写权限后: %d (二进制: %04b)\n", userPermissions, userPermissions)
}

快速数学运算

go
func main() {
    // 使用位运算进行快速计算
    n := 16
    
    // 判断是否为2的幂
    isPowerOfTwo := n > 0 && (n&(n-1)) == 0
    fmt.Printf("%d 是2的幂: %t\n", n, isPowerOfTwo)
    
    // 乘以2的幂(左移)
    fmt.Printf("%d * 4 = %d (使用 %d << 2)\n", n, n<<2, n)
    fmt.Printf("%d * 8 = %d (使用 %d << 3)\n", n, n<<3, n)
    
    // 除以2的幂(右移)
    fmt.Printf("%d / 4 = %d (使用 %d >> 2)\n", n, n>>2, n)
    fmt.Printf("%d / 8 = %d (使用 %d >> 3)\n", n, n>>3, n)
    
    // 获取最低位的1
    lowestBit := n & (-n)
    fmt.Printf("%d 的最低位1: %d\n", n, lowestBit)
    
    // 计算二进制中1的个数(Hamming重量)
    count := popCount(uint(n))
    fmt.Printf("%d 的二进制表示中1的个数: %d\n", n, count)
}

func popCount(x uint) int {
    count := 0
    for x != 0 {
        count++
        x &= x - 1  // 清除最低位的1
    }
    return count
}

📝 赋值运算符

基本赋值

go
func main() {
    var x int
    
    // 基本赋值
    x = 10
    fmt.Printf("x = %d\n", x)
    
    // 复合赋值运算符
    x += 5   // x = x + 5
    fmt.Printf("x += 5: %d\n", x)  // 15
    
    x -= 3   // x = x - 3
    fmt.Printf("x -= 3: %d\n", x)  // 12
    
    x *= 2   // x = x * 2
    fmt.Printf("x *= 2: %d\n", x)  // 24
    
    x /= 4   // x = x / 4
    fmt.Printf("x /= 4: %d\n", x)  // 6
    
    x %= 5   // x = x % 5
    fmt.Printf("x %%= 5: %d\n", x) // 1
}

位运算赋值

go
func main() {
    x := uint8(60)  // 0011 1100
    
    fmt.Printf("初始值 x = %d (二进制: %08b)\n", x, x)
    
    x &= 15   // x = x & 15 (0000 1111)
    fmt.Printf("x &= 15: %d (二进制: %08b)\n", x, x)  // 12 (0000 1100)
    
    x |= 3    // x = x | 3 (0000 0011)
    fmt.Printf("x |= 3: %d (二进制: %08b)\n", x, x)   // 15 (0000 1111)
    
    x ^= 5    // x = x ^ 5 (0000 0101)
    fmt.Printf("x ^= 5: %d (二进制: %08b)\n", x, x)   // 10 (0000 1010)
    
    x <<= 1   // x = x << 1
    fmt.Printf("x <<= 1: %d (二进制: %08b)\n", x, x)  // 20 (0001 0100)
    
    x >>= 2   // x = x >> 2
    fmt.Printf("x >>= 2: %d (二进制: %08b)\n", x, x)  // 5 (0000 0101)
}

多重赋值

go
func main() {
    // 多重赋值
    a, b, c := 1, 2, 3
    fmt.Printf("初始值: a=%d, b=%d, c=%d\n", a, b, c)
    
    // 交换变量
    a, b = b, a
    fmt.Printf("交换 a 和 b: a=%d, b=%d, c=%d\n", a, b, c)
    
    // 函数返回多个值
    x, y := divmod(17, 5)
    fmt.Printf("17 除以 5: 商=%d, 余数=%d\n", x, y)
    
    // 忽略某些值
    quotient, _ := divmod(20, 3)  // 忽略余数
    fmt.Printf("20 除以 3 的商: %d\n", quotient)
    
    // 批量赋值
    var (
        name string
        age  int
        city string
    )
    name, age, city = "张三", 25, "北京"
    fmt.Printf("个人信息: %s, %d岁, 来自%s\n", name, age, city)
}

func divmod(a, b int) (int, int) {
    return a / b, a % b
}

🎯 运算符优先级

优先级表

go
func main() {
    // Go 运算符优先级(从高到低)
    
    // 1. 最高优先级:一元运算符
    x := 5
    result1 := -x * 2    // -5 * 2 = -10
    fmt.Printf("-x * 2 = %d\n", result1)
    
    // 2. 乘除法、取余、位移、位与
    result2 := 2 + 3 * 4        // 2 + 12 = 14
    result3 := 8 << 1 + 1       // 8 << 2 = 32
    result4 := 12 & 7 + 1       // 12 & 8 = 8
    fmt.Printf("2 + 3 * 4 = %d\n", result2)
    fmt.Printf("8 << 1 + 1 = %d\n", result3)
    fmt.Printf("12 & 7 + 1 = %d\n", result4)
    
    // 3. 加减法、位或、位异或
    result5 := 1 + 2 << 3       // 1 + (2 << 3) = 1 + 16 = 17
    result6 := 5 | 2 + 1        // 5 | 3 = 7
    fmt.Printf("1 + 2 << 3 = %d\n", result5)
    fmt.Printf("5 | 2 + 1 = %d\n", result6)
    
    // 4. 比较运算符
    result7 := 1 + 2 == 3       // true
    result8 := 2 * 3 > 5        // true
    fmt.Printf("1 + 2 == 3: %t\n", result7)
    fmt.Printf("2 * 3 > 5: %t\n", result8)
    
    // 5. 逻辑与
    result9 := true && 2 > 1    // true
    fmt.Printf("true && 2 > 1: %t\n", result9)
    
    // 6. 逻辑或
    result10 := false || 3 < 5   // true
    fmt.Printf("false || 3 < 5: %t\n", result10)
}

使用括号明确优先级

go
func main() {
    // 不使用括号(依赖默认优先级)
    result1 := 2 + 3 * 4 - 1    // 2 + 12 - 1 = 13
    
    // 使用括号明确表达意图
    result2 := (2 + 3) * (4 - 1)  // 5 * 3 = 15
    result3 := 2 + (3 * 4) - 1    // 与result1相同,但更清晰
    
    fmt.Printf("默认优先级: 2 + 3 * 4 - 1 = %d\n", result1)
    fmt.Printf("使用括号: (2 + 3) * (4 - 1) = %d\n", result2)
    fmt.Printf("明确括号: 2 + (3 * 4) - 1 = %d\n", result3)
    
    // 复杂表达式
    a, b, c := 2, 3, 4
    complex1 := a + b * c > 10 && a < b || c == 4
    complex2 := ((a + (b * c)) > 10) && (a < b) || (c == 4)
    
    fmt.Printf("复杂表达式1: %t\n", complex1)
    fmt.Printf("复杂表达式2: %t\n", complex2)
}

🎯 实际应用示例

数学计算器

go
import "fmt"

func main() {
    // 简单计算器
    calculator := NewCalculator()
    
    // 基本运算
    fmt.Printf("10 + 5 = %.2f\n", calculator.Add(10, 5))
    fmt.Printf("10 - 5 = %.2f\n", calculator.Subtract(10, 5))
    fmt.Printf("10 * 5 = %.2f\n", calculator.Multiply(10, 5))
    fmt.Printf("10 / 5 = %.2f\n", calculator.Divide(10, 5))
    
    // 高级运算
    fmt.Printf("2^8 = %.0f\n", calculator.Power(2, 8))
    fmt.Printf("√16 = %.2f\n", calculator.SquareRoot(16))
    fmt.Printf("10%% = %.2f\n", calculator.Percentage(10))
}

type Calculator struct{}

func NewCalculator() *Calculator {
    return &Calculator{}
}

func (c *Calculator) Add(a, b float64) float64 {
    return a + b
}

func (c *Calculator) Subtract(a, b float64) float64 {
    return a - b
}

func (c *Calculator) Multiply(a, b float64) float64 {
    return a * b
}

func (c *Calculator) Divide(a, b float64) float64 {
    if b == 0 {
        panic("除数不能为零")
    }
    return a / b
}

func (c *Calculator) Power(base, exp float64) float64 {
    result := 1.0
    for i := 0; i < int(exp); i++ {
        result *= base
    }
    return result
}

func (c *Calculator) SquareRoot(n float64) float64 {
    if n < 0 {
        panic("负数没有实数平方根")
    }
    // 牛顿法求平方根
    x := n
    for i := 0; i < 10; i++ {
        x = (x + n/x) / 2
    }
    return x
}

func (c *Calculator) Percentage(n float64) float64 {
    return n / 100
}

🎓 小结

本章我们全面学习了 Go 语言的运算符:

  • 算术运算符:+、-、*、/、%、++、--
  • 比较运算符:==、!=、<、<=、>、>=
  • 逻辑运算符:&&、||、!,短路求值
  • 位运算符:&、|、^、<<、>>、&^
  • 赋值运算符:=、+=、-=、*=、/=、%=等
  • 运算符优先级:优先级规则和括号使用

掌握运算符的正确使用是编写高效 Go 代码的基础,特别是位运算符在系统编程和性能优化中有重要作用。


接下来,我们将学习 Go 语言条件语句,掌握程序的分支控制。

运算符使用建议

  • 使用括号明确复杂表达式的运算顺序
  • 注意浮点数比较的精度问题
  • 利用位运算进行高效的标志位操作
  • 善用短路求值提高程序性能

本站内容仅供学习和研究使用。