TL;DR:本文介绍了在Golang中的算术运算符
运算符是程序里最基础的计算工具。本篇会把 Go 的所有运算符过一遍,重点放在和其他语言不同的地方
算术运算符
最基本的数学运算:
| 运算符 | 含义 | 示例 |
|---|---|---|
+ | 加 | 1 + 2 = 3 |
- | 减 | 5 - 3 = 2 |
* | 乘 | 3 * 4 = 12 |
/ | 除 | 10 / 3 = 3 |
% | 取余 | 10 % 3 = 1 |
简单吧,但是除法要注意下
整数除法直接截断:
fmt.Println(10 / 3) // 3,不是 3.333...fmt.Println(10.0 / 3) // 3.3333333333333335两个整数相除,结果还是整数,小数部分直接丢掉。要得到小数结果,必须有一方是浮点数:
a := 10b := 3fmt.Println(float64(a) / float64(b)) // 3.3333333333333335取余的结果符号和被除数一致:
fmt.Println(10 % 3) // 1fmt.Println(-10 % 3) // -1,结果是负数fmt.Println(10 % -3) // 1,结果是正数取余结果的正负,跟被除数(左边那个数)一致,和除数(右边)无关
+ 用于字符串拼接:
a := "Hello"b := "Go"fmt.Println(a + ", " + b + "!") // Hello, Go!自增和自减
Go 有 ++ 和 --,但和其他语言有个重要区别:
a := 1a++ // a = 2a-- // a = 1Go 的 ++ 和 -- 是语句,不是表达式,不能放在赋值右边:
a := 1b := a++ // ❌ 报错也没有前置的 ++a:
++a // ❌ 报错只有 a++ 和 a--,而且只能单独成行。Go 的设计去掉了 i++ + ++i 这类让人困惑的写法
赋值运算符
基本赋值:
a := 10a = 20 // 重新赋值复合赋值,把运算和赋值合在一起:
a := 10a += 5 // a = a + 5 = 15a -= 3 // a = a - 3 = 12a *= 2 // a = a * 2 = 24a /= 4 // a = a / 4 = 6a %= 4 // a = a % 4 = 2字符串也可以用 +=:
s := "Hello"s += ", Go!"fmt.Println(s) // Hello, Go!比较运算符
比较运算符的结果是布尔值 true 或 false:
| 运算符 | 含义 |
|---|---|
== | 等于 |
!= | 不等于 |
> | 大于 |
< | 小于 |
>= | 大于等于 |
<= | 小于等于 |
fmt.Println(1 == 1) // truefmt.Println(1 != 2) // truefmt.Println(3 > 2) // truefmt.Println(3 < 2) // false只有相同类型才能比较:
var a int = 1var b int32 = 1fmt.Println(a == b) // ❌ 报错,int 和 int32 不同类型必须转换成同一类型再比较:
fmt.Println(a == int(b)) // ✅ true字符串比较按字典序:
fmt.Println("abc" == "abc") // truefmt.Println("abc" < "abd") // true,c < dfmt.Println("abc" > "ab") // true,更长的字符串更大浮点数比较要小心:
a := 0.1 + 0.2b := 0.3fmt.Println(a == b) // false,精度问题浮点数不能直接用 == 比较,应该判断差值是否足够小:
import "math"
diff := math.Abs(a - b)fmt.Println(diff < 1e-9) // true,认为相等逻辑运算符
用于组合多个布尔条件:
| 运算符 | 含义 | 示例 |
|---|---|---|
&& | 与,两边都为 true 才是 true | true && false = false |
|| | 或,一边为 true 就是 true | true || false = true |
! | 非,取反 | !true = false |
age := 20hasID := true
// 成年且有证件if age >= 18 && hasID { fmt.Println("pass")}
// 是管理员或者是超级用户isAdmin := falseisSuperUser := trueif isAdmin || isSuperUser { fmt.Println("pass")}
// 不是访客isGuest := falseif !isGuest { fmt.Println("not guess")}短路求值
&& 和 || 都有短路特性:
// && 左边是 false,右边不会执行false && someFunc() // someFunc() 不会被调用
// || 左边是 true,右边不会执行true || someFunc() // someFunc() 不会被调用利用这个特性可以避免空指针等问题:
// 先检查 user 不为空,再访问 user.Nameif user != nil && user.Name == "admin" { fmt.Println("是管理员")}如果 user 是 nil,&& 短路,不会执行右边,就不会因为访问 nil 的字段而崩溃
位运算符
位运算直接操作二进制位,在处理权限、标志位、底层协议时很常用:
| 运算符 | 含义 | 示例 |
|---|---|---|
& | 按位与 | 0101 & 0011 = 0001 |
| | 按位或 | 0101 | 0011 = 0111 |
^ | 按位异或 | 0101 ^ 0011 = 0110 |
<< | 左移 | 1 << 3 = 8 |
>> | 右移 | 8 >> 1 = 4 |
&^ | 按位清零(Go 特有) | 0101 &^ 0011 = 0100 |
左移和右移
左移一位相当于乘以 2,右移一位相当于除以 2:
fmt.Println(1 << 3) // 8,1 × 2³fmt.Println(8 >> 1) // 4,8 ÷ 2上一篇 iota 里定义文件大小就是用的左移:
const ( _ = iota KB = 1 << (10 * iota) // 1024 MB // 1048576 GB // 1073741824)按位与用来检查标志位:
const ( PermRead = 1 << iota // 001 PermWrite // 010 PermExecute // 100)
perm := PermRead | PermWrite // 011,有读和写权限
// 检查是否有读权限if perm & PermRead != 0 { fmt.Println("有读权限")}
// 检查是否有执行权限if perm & PermExecute != 0 { fmt.Println("有执行权限")} else { fmt.Println("没有执行权限")}&^ 按位清零,Go 特有
a &^ b 的意思是:把 b 中为 1 的位,在 a 中清零:
perm := PermRead | PermWrite // 011
// 去掉写权限perm = perm &^ PermWrite // 001fmt.Println(perm & PermWrite != 0) // false,写权限没了其他语言一般用 a & ~b 实现同样效果,Go 的这个操作单独成一个运算符
运算优先级
当一个表达式里有多个运算符时,优先级决定计算顺序。Go 的优先级从高到低:
| 优先级 | 运算符 |
|---|---|
| 5(最高) | * / % << >> & &^ |
| 4 | + - | ^ |
| 3 | == != < <= > >= |
| 2 | && |
| 1(最低) | || |
fmt.Println(2 + 3*4) // 14,乘法优先fmt.Println(2 > 1 && 3 > 2) // true,比较优先于 &&不要依赖优先级,用括号写清楚:
// 不清晰result := a + b * c >> 2 & mask
// 清晰result := ((a + (b * c)) >> 2) & mask优先级规则不用背,遇到不确定的就加括号,清晰又不易错
运算符的一些细节
^ 在 Go 里有两个用途
作为二元运算符是按位异或:
fmt.Println(5 ^ 3) // 6,0101 ^ 0011 = 0110作为一元运算符是按位取反(其他语言一般用 ~):
var a uint8 = 5 // 00000101fmt.Println(^a) // 250,11111010整数除法和取余的关系
a, b := 10, 3q := a / b // 商 3r := a % b // 余数 1
// 验证:q*b + r == a 永远成立fmt.Println(q*b+r == a) // true字符串不支持 -、*、/ 运算:
"hello" - "world" // ❌ 报错"hello" * 3 // ❌ 报错,Python 里可以但 Go 不行字符串重复用 strings.Repeat():
fmt.Println(strings.Repeat("go", 3)) // gogogo下一篇讲 if 语句,条件判断的完整用法,以及 Go 里 if 特有的初始化语句写法
Auth_Verified: 2026.05.15