Go学习笔记-Operators

Go语言提供了丰富的操作符,包括算术、比较、逻辑、位运算等操作符。理解这些操作符的使用方法和优先级对编写正确的程序很重要。

算术操作符

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
package main

import "fmt"

func main() {
    a, b := 10, 3
    
    // 基本算术操作符
    fmt.Printf("a = %d, b = %d\n", a, b)
    fmt.Printf("a + b = %d\n", a+b)  // 加法
    fmt.Printf("a - b = %d\n", a-b)  // 减法
    fmt.Printf("a * b = %d\n", a*b)  // 乘法
    fmt.Printf("a / b = %d\n", a/b)  // 除法(整数除法)
    fmt.Printf("a %% b = %d\n", a%b) // 取模
    
    // 浮点数除法
    x, y := 10.0, 3.0
    fmt.Printf("x / y = %.2f\n", x/y)
    
    // 自增和自减操作符
    i := 5
    fmt.Printf("i = %d\n", i)
    i++  // 自增
    fmt.Printf("i++ 后 i = %d\n", i)
    i--  // 自减
    fmt.Printf("i-- 后 i = %d\n", i)
    
    // 注意:Go中++和--是语句,不是表达式
    // fmt.Println(++i) // 错误
    // fmt.Println(i++) // 错误
    
    // 复合赋值操作符
    num := 10
    fmt.Printf("初始值 num = %d\n", num)
    
    num += 5   // 等价于 num = num + 5
    fmt.Printf("num += 5 后 num = %d\n", num)
    
    num -= 3   // 等价于 num = num - 3
    fmt.Printf("num -= 3 后 num = %d\n", num)
    
    num *= 2   // 等价于 num = num * 2
    fmt.Printf("num *= 2 后 num = %d\n", num)
    
    num /= 4   // 等价于 num = num / 4
    fmt.Printf("num /= 4 后 num = %d\n", num)
    
    num %= 3   // 等价于 num = num % 3
    fmt.Printf("num %%= 3 后 num = %d\n", num)
}

比较操作符

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
package main

import "fmt"

func main() {
    a, b := 10, 20
    
    fmt.Printf("a = %d, b = %d\n", a, b)
    
    // 相等性比较
    fmt.Printf("a == b: %t\n", a == b)  // 等于
    fmt.Printf("a != b: %t\n", a != b)  // 不等于
    
    // 大小比较
    fmt.Printf("a < b: %t\n", a < b)    // 小于
    fmt.Printf("a <= b: %t\n", a <= b)  // 小于等于
    fmt.Printf("a > b: %t\n", a > b)    // 大于
    fmt.Printf("a >= b: %t\n", a >= b)  // 大于等于
    
    // 字符串比较
    str1, str2 := "apple", "banana"
    fmt.Printf("str1 = %s, str2 = %s\n", str1, str2)
    fmt.Printf("str1 == str2: %t\n", str1 == str2)
    fmt.Printf("str1 < str2: %t\n", str1 < str2)  // 字典序比较
    
    // 数组比较(相同类型和长度的数组可以比较)
    arr1 := [3]int{1, 2, 3}
    arr2 := [3]int{1, 2, 3}
    arr3 := [3]int{1, 2, 4}
    
    fmt.Printf("arr1 == arr2: %t\n", arr1 == arr2)
    fmt.Printf("arr1 == arr3: %t\n", arr1 == arr3)
    
    // 切片不能直接比较(除了与nil比较)
    slice1 := []int{1, 2, 3}
    fmt.Printf("slice1 == nil: %t\n", slice1 == nil)
    
    // 指针比较
    x, y := 42, 42
    ptr1, ptr2 := &x, &y
    ptr3 := &x
    
    fmt.Printf("ptr1 == ptr2: %t\n", ptr1 == ptr2)  // false,不同的内存地址
    fmt.Printf("ptr1 == ptr3: %t\n", ptr1 == ptr3)  // true,相同的内存地址
    fmt.Printf("*ptr1 == *ptr2: %t\n", *ptr1 == *ptr2)  // true,值相同
}

逻辑操作符

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
package main

import "fmt"

func main() {
    a, b := true, false
    
    fmt.Printf("a = %t, b = %t\n", a, b)
    
    // 逻辑与(AND)
    fmt.Printf("a && b: %t\n", a && b)
    fmt.Printf("a && true: %t\n", a && true)
    fmt.Printf("false && b: %t\n", false && b)
    
    // 逻辑或(OR)
    fmt.Printf("a || b: %t\n", a || b)
    fmt.Printf("a || false: %t\n", a || false)
    fmt.Printf("false || false: %t\n", false || false)
    
    // 逻辑非(NOT)
    fmt.Printf("!a: %t\n", !a)
    fmt.Printf("!b: %t\n", !b)
    fmt.Printf("!!a: %t\n", !!a)
    
    // 短路求值
    fmt.Println("\n短路求值演示:")
    
    // 逻辑与的短路求值
    if false && printAndReturnTrue("这不会被打印") {
        fmt.Println("不会执行")
    }
    
    if true && printAndReturnTrue("这会被打印") {
        fmt.Println("会执行")
    }
    
    // 逻辑或的短路求值
    if true || printAndReturnTrue("这不会被打印") {
        fmt.Println("会执行")
    }
    
    if false || printAndReturnTrue("这会被打印") {
        fmt.Println("会执行")
    }
    
    // 复杂逻辑表达式
    x, y, z := 5, 10, 15
    
    result := (x < y) && (y < z) && (x+y > z-5)
    fmt.Printf("复杂逻辑表达式结果: %t\n", result)
    
    // 使用逻辑操作符进行条件检查
    age := 25
    hasLicense := true
    
    canDrive := age >= 18 && hasLicense
    fmt.Printf("可以开车: %t\n", canDrive)
    
    isTeenager := age >= 13 && age <= 19
    fmt.Printf("是青少年: %t\n", isTeenager)
}

func printAndReturnTrue(msg string) bool {
    fmt.Println(msg)
    return true
}

位操作符

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
package main

import "fmt"

func main() {
    a, b := 12, 10  // 二进制: a=1100, b=1010
    
    fmt.Printf("a = %d (二进制: %04b)\n", a, a)
    fmt.Printf("b = %d (二进制: %04b)\n", b, b)
    
    // 位与(AND)
    and := a & b
    fmt.Printf("a & b = %d (二进制: %04b)\n", and, and)
    
    // 位或(OR)
    or := a | b
    fmt.Printf("a | b = %d (二进制: %04b)\n", or, or)
    
    // 位异或(XOR)
    xor := a ^ b
    fmt.Printf("a ^ b = %d (二进制: %04b)\n", xor, xor)
    
    // 位清除(AND NOT)
    andNot := a &^ b
    fmt.Printf("a &^ b = %d (二进制: %04b)\n", andNot, andNot)
    
    // 位取反(NOT)
    not := ^a
    fmt.Printf("^a = %d (二进制: %032b)\n", not, not)
    
    // 左移位
    leftShift := a << 2
    fmt.Printf("a << 2 = %d (二进制: %08b)\n", leftShift, leftShift)
    
    // 右移位
    rightShift := a >> 2
    fmt.Printf("a >> 2 = %d (二进制: %04b)\n", rightShift, rightShift)
    
    // 位操作的实际应用
    fmt.Println("\n位操作的实际应用:")
    
    // 检查奇偶性
    num := 17
    if num&1 == 0 {
        fmt.Printf("%d 是偶数\n", num)
    } else {
        fmt.Printf("%d 是奇数\n", num)
    }
    
    // 设置标志位
    var flags uint8 = 0
    const (
        FlagRead  = 1 << 0  // 0001
        FlagWrite = 1 << 1  // 0010
        FlagExec  = 1 << 2  // 0100
    )
    
    // 设置读权限
    flags |= FlagRead
    fmt.Printf("设置读权限后: %08b\n", flags)
    
    // 设置写权限
    flags |= FlagWrite
    fmt.Printf("设置写权限后: %08b\n", flags)
    
    // 检查是否有读权限
    if flags&FlagRead != 0 {
        fmt.Println("有读权限")
    }
    
    // 清除写权限
    flags &^= FlagWrite
    fmt.Printf("清除写权限后: %08b\n", flags)
    
    // 切换执行权限
    flags ^= FlagExec
    fmt.Printf("切换执行权限后: %08b\n", flags)
}

赋值操作符

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
package main

import "fmt"

func main() {
    // 简单赋值
    var a int
    a = 10
    fmt.Printf("a = %d\n", a)
    
    // 多重赋值
    x, y := 1, 2
    fmt.Printf("x = %d, y = %d\n", x, y)
    
    // 交换变量
    x, y = y, x
    fmt.Printf("交换后: x = %d, y = %d\n", x, y)
    
    // 函数返回多个值的赋值
    quotient, remainder := divmod(17, 5)
    fmt.Printf("17 ÷ 5 = %d 余 %d\n", quotient, remainder)
    
    // 忽略某些返回值
    result, _ := divmod(20, 3)
    fmt.Printf("20 ÷ 3 = %d\n", result)
    
    // 复合赋值操作符
    num := 100
    fmt.Printf("初始值: %d\n", num)
    
    num += 50   // 加法赋值
    fmt.Printf("num += 50: %d\n", num)
    
    num -= 30   // 减法赋值
    fmt.Printf("num -= 30: %d\n", num)
    
    num *= 2    // 乘法赋值
    fmt.Printf("num *= 2: %d\n", num)
    
    num /= 4    // 除法赋值
    fmt.Printf("num /= 4: %d\n", num)
    
    num %= 7    // 取模赋值
    fmt.Printf("num %%= 7: %d\n", num)
    
    // 位操作赋值
    bits := 12  // 1100
    fmt.Printf("初始位值: %d (%04b)\n", bits, bits)
    
    bits &= 10  // 位与赋值 (1100 & 1010 = 1000)
    fmt.Printf("bits &= 10: %d (%04b)\n", bits, bits)
    
    bits |= 5   // 位或赋值 (1000 | 0101 = 1101)
    fmt.Printf("bits |= 5: %d (%04b)\n", bits, bits)
    
    bits ^= 3   // 位异或赋值 (1101 ^ 0011 = 1110)
    fmt.Printf("bits ^= 3: %d (%04b)\n", bits, bits)
    
    bits <<= 1  // 左移赋值 (1110 << 1 = 11100)
    fmt.Printf("bits <<= 1: %d (%05b)\n", bits, bits)
    
    bits >>= 2  // 右移赋值 (11100 >> 2 = 111)
    fmt.Printf("bits >>= 2: %d (%03b)\n", bits, bits)
    
    // 指针赋值
    var ptr *int
    value := 42
    ptr = &value
    fmt.Printf("指针指向的值: %d\n", *ptr)
    
    *ptr = 100  // 通过指针修改值
    fmt.Printf("修改后的值: %d\n", value)
}

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

其他操作符

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
package main

import "fmt"

func main() {
    // 1. 地址操作符 &
    num := 42
    ptr := &num
    fmt.Printf("num的值: %d\n", num)
    fmt.Printf("num的地址: %p\n", ptr)
    
    // 2. 解引用操作符 *
    fmt.Printf("ptr指向的值: %d\n", *ptr)
    *ptr = 100
    fmt.Printf("通过指针修改后num的值: %d\n", num)
    
    // 3. 通道操作符 <-
    ch := make(chan int, 1)
    
    // 发送数据到通道
    ch <- 42
    fmt.Println("数据已发送到通道")
    
    // 从通道接收数据
    value := <-ch
    fmt.Printf("从通道接收到的值: %d\n", value)
    
    // 4. 类型断言操作符 .(type)
    var i interface{} = "hello"
    
    // 类型断言
    if str, ok := i.(string); ok {
        fmt.Printf("类型断言成功: %s\n", str)
    }
    
    // 类型选择
    switch v := i.(type) {
    case string:
        fmt.Printf("这是字符串: %s\n", v)
    case int:
        fmt.Printf("这是整数: %d\n", v)
    default:
        fmt.Printf("未知类型: %T\n", v)
    }
    
    // 5. 切片操作符 [:]
    arr := []int{1, 2, 3, 4, 5}
    fmt.Printf("原数组: %v\n", arr)
    fmt.Printf("arr[1:4]: %v\n", arr[1:4])
    fmt.Printf("arr[:3]: %v\n", arr[:3])
    fmt.Printf("arr[2:]: %v\n", arr[2:])
    fmt.Printf("arr[:]: %v\n", arr[:])
    
    // 6. 函数调用操作符 ()
    result := add(10, 20)
    fmt.Printf("函数调用结果: %d\n", result)
    
    // 7. 索引操作符 []
    slice := []string{"apple", "banana", "cherry"}
    fmt.Printf("slice[1]: %s\n", slice[1])
    
    m := map[string]int{"go": 1, "python": 2}
    fmt.Printf("m[\"go\"]: %d\n", m["go"])
    
    // 8. 结构体字段访问操作符 .
    type Person struct {
        Name string
        Age  int
    }
    
    p := Person{Name: "张三", Age: 25}
    fmt.Printf("姓名: %s, 年龄: %d\n", p.Name, p.Age)
    
    // 通过指针访问结构体字段
    pPtr := &p
    fmt.Printf("通过指针访问姓名: %s\n", pPtr.Name)
}

func add(a, b int) int {
    return a + b
}

操作符优先级

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
package main

import "fmt"

func main() {
    // Go语言操作符优先级(从高到低):
    // 1. () [] -> .
    // 2. + - ! ^ * & (一元操作符)
    // 3. * / % << >> & &^
    // 4. + - | ^
    // 5. == != < <= > >=
    // 6. &&
    // 7. ||
    
    // 示例1:算术操作符优先级
    result1 := 2 + 3 * 4
    fmt.Printf("2 + 3 * 4 = %d\n", result1)  // 14,不是20
    
    result2 := (2 + 3) * 4
    fmt.Printf("(2 + 3) * 4 = %d\n", result2)  // 20
    
    // 示例2:位操作符优先级
    a := 5   // 101
    b := 3   // 011
    result3 := a | b & 1
    fmt.Printf("5 | 3 & 1 = %d\n", result3)  // 5,因为&优先级高于|
    
    result4 := (a | b) & 1
    fmt.Printf("(5 | 3) & 1 = %d\n", result4)  // 1
    
    // 示例3:比较和逻辑操作符优先级
    x, y, z := 5, 10, 15
    result5 := x < y && y < z || x > z
    fmt.Printf("5 < 10 && 10 < 15 || 5 > 15 = %t\n", result5)  // true
    
    // 等价于:(x < y && y < z) || x > z
    result6 := (x < y && y < z) || x > z
    fmt.Printf("(5 < 10 && 10 < 15) || 5 > 15 = %t\n", result6)  // true
    
    // 示例4:复杂表达式
    num := 10
    result7 := num > 5 && num < 20 || num == 0
    fmt.Printf("10 > 5 && 10 < 20 || 10 == 0 = %t\n", result7)  // true
    
    // 建议:使用括号明确表达意图
    result8 := (num > 5 && num < 20) || (num == 0)
    fmt.Printf("(10 > 5 && 10 < 20) || (10 == 0) = %t\n", result8)  // true
    
    // 示例5:赋值操作符优先级最低
    var flag bool
    flag = x < y && y < z  // 先计算右边的表达式,再赋值
    fmt.Printf("flag = %t\n", flag)
}

总结

  1. 算术操作符+, -, *, /, %, ++, --
  2. 比较操作符==, !=, <, <=, >, >=
  3. 逻辑操作符&&, ||, !(支持短路求值)
  4. 位操作符&, |, ^, &^, <<, >>, ^
  5. 赋值操作符=, +=, -=, *=, /=, %=, &=, |=, ^=, <<=, >>=
  6. 其他操作符
    • 地址操作符:&
    • 解引用操作符:*
    • 通道操作符:<-
    • 类型断言:.(type)
    • 切片操作符:[:]
  7. 优先级:使用括号明确表达意图,避免依赖操作符优先级
  8. 特点
    • ++--是语句,不是表达式
    • 支持多重赋值
    • 逻辑操作符支持短路求值
    • 位操作符功能强大,适用于底层编程
updatedupdated2025-09-202025-09-20