目录

一次性带你彻底学透 Golang 操作运算符

Golang 运算符分类总览

Golang 运算符按功能可分为 5 大类:算术运算符、赋值运算符、比较运算符、逻辑运算符、位运算符。

不同类型的运算符有明确的使用场景和优先级。

提示:Golang 没有三元运算符(如 a?b:c),这是和其他语言的明显区别。

算术运算符

处理数值计算的核心

算术运算符用于整数、浮点数的加减乘除等计算,共 7 个,其中取模(%)和自增自减(++、–)。

package main

import "fmt"

func main() {
    // 基础算术运算:+ - * /
    a, b := 10, 3
    fmt.Println("a + b =", a + b) // 输出 13
    fmt.Println("a - b =", a - b) // 输出 7
    fmt.Println("a * b =", a * b) // 输出 30
    // 除法注意:Golang 中整数相除结果取整,浮点数相除才保留小数
    fmt.Println("a / b =", a / b) // 输出 3(不是 3.333)
    fmt.Println("a / float64(b) =", float64(a) / float64(b)) // 输出 3.333...

    // 取模运算:结果符号与被除数一致
    fmt.Println("a % b =", a % b)  // 输出 1(10 = 3*3 +1)
    fmt.Println("-a % b =", -a % b) // 输出 -1(符号随被除数 -10)

    // 自增自减:只能独立使用,不能参与表达式计算
    c := 5
    c++ // 正确:等价于 c = c + 1
    // fmt.Println(c++) // 错误:不能直接用于输出等表达式
    fmt.Println("c++ 后 =", c) // 输出 6

    d := 8
    d--
    fmt.Println("d-- 后 =", d) // 输出 7
}

整数除法会自动舍弃小数部分,若要保留小数需先转成 float64 类型;自增自减只能单独成句,不能写在 fmt.Println(a++) 这类表达式里,这是 Golang 独有的语法限制

赋值运算符

简化赋值逻辑

赋值运算符以 = 为基础,衍生出复合赋值(如 +=、*=),核心作用是简化变量赋值代码,提高可读性。

package main

import "fmt"

func main() {
    // 基础赋值
    var x int
    x = 10
    fmt.Println("基础赋值 x =", x) // 输出 10

    // 复合赋值:等价于 变量 = 变量 运算符 右值
    x += 5  // 等价于 x = x + 5
    fmt.Println("x += 5 后 =", x) // 输出 15

    x *= 2  // 等价于 x = x * 2
    fmt.Println("x *= 2 后 =", x) // 输出 30

    x %= 4  // 等价于 x = x % 4
    fmt.Println("x %= 4 后 =", x) // 输出 2

    // 多重赋值:Golang 特色,可交换变量值
    y, z := 20, 30
    y, z = z, y // 无需临时变量直接交换
    fmt.Println("交换后 y =", y, "z =", z) // 输出 30 20
} 

多重赋值在变量交换、函数返回多值接收时特别好用,比如接收 err 信息时的 data, err := func(),就是依托多重赋值实现的。

比较运算符

判断条件的“开关”

比较运算符用于判断两个值的关系,返回结果只有 truefalse,是 iffor 等流程控制的核心。

package main

import "fmt"

func main() {
    m, n := 15, 25
    // 基本比较:== != > < >= <=
    fmt.Println("m == n ?", m == n) // 输出 false
    fmt.Println("m != n ?", m != n) // 输出 true
    fmt.Println("m > n ?", m > n)   // 输出 false
    fmt.Println("m <= n ?", m <= n) // 输出 true

    // 注意:Golang 中不能连写比较,如 10 < m < 20 是错误的
    // 正确写法:使用逻辑运算符连接
    fmt.Println("m 在 10-20 之间?", m > 10 && m < 20) // 输出 true
}

不要像数学公式那样连写比较(如 5 < x < 10),Golang 不支持这种语法,必须用逻辑运算符 && 拆分。

逻辑运算符

组合条件判断

逻辑运算符有 3 个:&&(与)、||(或)、!(非),用于组合多个比较条件,核心特性是“短路求值”。

package main

import "fmt"

func main() {
    p, q := true, false
    // 逻辑与 &&:两边都为 true 才返回 true,左边为 false 则不执行右边
    fmt.Println("p && q ?", p && q) // 输出 false

    // 逻辑或 ||:左边为 true 则不执行右边,直接返回 true
    fmt.Println("p || q ?", p || q) // 输出 true

    // 逻辑非 !:取反
    fmt.Println("!p ?", !p) // 输出 false

    // 短路求值实例:右边函数不会执行
    fmt.Println("短路测试:", q && testFunc()) // 输出 false,testFunc 未执行
}

func testFunc() bool {
    fmt.Println("testFunc 执行了")
    return true
}

&& 左边为 false 时,右边代码直接跳过;|| 左边为 true 时,右边代码直接跳过。

这个特性可用于避免空指针报错,比如 obj != nil && obj.Name != "",若 obj 为空则不会执行后面的属性获取。

位运算符

操作二进制的“底层工具”

位运算符直接操作数值的二进制位,多用于底层开发、加密、性能优化等场景,开发者可能接触较少但必须了解基础用法。

package main

import "fmt"

func main() {
    // 以 10(二进制 1010)和 3(二进制 0011)为例
    s, t := 10, 3

    // 按位与 &:对应位都为 1 则为 1
    fmt.Println("s & t =", s & t) // 二进制 0010 → 输出 2

    // 按位或 |:对应位有一个为 1 则为 1
    fmt.Println("s | t =", s | t) // 二进制 1011 → 输出 11

    // 按位异或 ^:对应位不同则为 1
    fmt.Println("s ^ t =", s ^ t) // 二进制 1001 → 输出 9

    // 左移 <<:整体左移,右边补 0(等价于乘以 2 的 n 次方)
    fmt.Println("s << 1 =", s << 1) // 二进制 10100 → 输出 20(10*2)

    // 右移 >>:整体右移,左边补符号位(等价于除以 2 的 n 次方)
    fmt.Println("s >> 1 =", s >> 1) // 二进制 0101 → 输出 5(10/2)
}

左移右移比乘法除法运算更快,比如 x << 2x * 4 性能更高;异或运算可用于简单加密(两次异或同一值还原原数)。

总览详情

位操作 含义 备注
& 按位与 两个操作数对应的二进制位,都为1则为1,否则为0
按位或 两个操作数对应的二进制位,有1则为1,否则为0
~ 按位非 两个操作数对应的二进制位,取反操作,1则为0,0则为1
^ 异或 两个操作数对应的二进制位,相同为0,相异为1
« 左移 将二进制位全部左移n位,相当于乘以2的n次方,如1«6 相当于1×64=64
» 右移 将二进制位全部右移n位,相当于除以2的n次方,如64»3 相当于64÷8=8

运算符优先级与结合性

很多错误都是因为搞混优先级导致的,比如 1 + 2 * 3 结果是 7 不是 9。

下面整理了 Golang 运算符的优先级(从高到低),标红的是高频使用的:

优先级 运算符类型 具体运算符 结合性
1(最高) 括号 () 从左到右
2 自增自减、取反 ++、–、!、^(按位非) 从右到左
3 算术运算符(乘除取模) *、/、% 从左到右
4 算术运算符(加减) +、- 从左到右
5 位运算符(移位) «、» 从左到右
6 比较运算符 ==、!=、>、<、>=、<= 从左到右
7 位运算符(与或异或) &、^、| 从左到右
8 逻辑运算符 &&、| 从左到右
9(最低) 赋值运算符 = 从右到左

优先级记不准时,直接加括号!括号的优先级最高,能明确改变运算顺序,比如 (1 + 2) * 3 比死记优先级更可靠。

常见问题

Q1. 自增自减用于表达式导致编译报错

问题代码fmt.Println(a++)b := a++

原因:Golang 规定自增自减只能作为独立语句,不能参与赋值、输出等表达式运算,这和 Java、C++ 不同。

解决办法:先执行自增自减,再使用变量

a := 5
a++ // 先自增
fmt.Println(a) // 正确,输出 6

b := a
a++ // 先赋值再自增
fmt.Println(b) // 正确,输出 6

Q2. 逻辑运算符与位运算符混淆

问题代码:用 & 代替 && 判断条件:if a > 10 & b < 20 {}

原因& 是位运算符,&& 是逻辑运算符,两者优先级不同(& 比 && 高),混用会导致逻辑错误。

解决办法:判断条件用逻辑运算符 &&||,位运算只用于二进制操作。

a, b := 15, 18
// 正确:逻辑与判断条件
if a > 10 && b < 20 {
    fmt.Println("条件成立")
}

Q3. 优先级错误导致计算结果异常

问题代码result := 10 + 20 * 3 - 5 想先算 10+20 和 3-5,结果得到 65 不是 295。

原因:乘法优先级高于加减,代码实际执行顺序是 10 + (20*3) -5

解决办法:用括号明确指定运算顺序。

// 正确:先算括号内的加法和减法
result := (10 + 20) * (3 - 5)
fmt.Println(result) // 输出 -60(符合预期)

Q4. 位运算右移时符号位问题

问题代码:负数右移后结果不符合预期:fmt.Println(-10 >> 1) 输出 -5 不是 5。

原因:Golang 中右移运算符 >> 是“算术右移”,负数的符号位(最高位)会补 1,而不是补 0。

解决办法:若要实现“逻辑右移”(不管正负都补 0),需先将负数转成无符号整数。

num := -10
// 算术右移:符号位补 1,结果 -5
fmt.Println(num >> 1)
// 逻辑右移:转无符号整数后右移,结果 9223372036854775803(二进制高位补 0)
fmt.Println(uint64(num) >> 1)

总结

运算符看似基础,但想真正掌握就必须“练+避坑”:

基础用法靠实例代码巩固,比如写一段包含所有运算符的小脚本运行调试;

易错点靠总结记忆,比如自增自减的使用限制、短路特性的应用;

优先级记不准就加括号,不要靠“语感”写代码。

建议把把这些实例和错误整理到笔记里,遇到问题就翻出来对比,慢慢就形成了肌肉记忆。

如果你在实际使用中还遇到过其他运算符的坑,欢迎在评论区分享,咱们一起避坑~

版权声明

未经授权,禁止转载本文章。
如需转载请保留原文链接并注明出处。即视为默认获得授权。
未保留原文链接未注明出处或删除链接将视为侵权,必追究法律责任!

本文原文链接: https://fiveyoboy.com/articles/golang-bitwise-operators-guide/

备用原文链接: https://blog.fiveyoboy.com/articles/golang-bitwise-operators-guide/