惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

P
Proofpoint News Feed
博客园_首页
WordPress大学
WordPress大学
大猫的无限游戏
大猫的无限游戏
有赞技术团队
有赞技术团队
阮一峰的网络日志
阮一峰的网络日志
Hugging Face - Blog
Hugging Face - Blog
博客园 - 【当耐特】
酷 壳 – CoolShell
酷 壳 – CoolShell
Y
Y Combinator Blog
Vercel News
Vercel News
The GitHub Blog
The GitHub Blog
T
The Blog of Author Tim Ferriss
云风的 BLOG
云风的 BLOG
博客园 - 司徒正美
Engineering at Meta
Engineering at Meta
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
J
Java Code Geeks
Stack Overflow Blog
Stack Overflow Blog
N
Netflix TechBlog - Medium
Martin Fowler
Martin Fowler
宝玉的分享
宝玉的分享
G
Google Developers Blog
Last Week in AI
Last Week in AI

Chongxiの咖啡屋

Google相册迁移到iCloud分享 - Chongxiの咖啡屋 讲讲「万物皆虚,万事皆允」 - Chongxiの咖啡屋 舞萌DX 落雪查分器使用指南 - Chongxiの咖啡屋 现代人的刻舟求剑 - Chongxiの咖啡屋 舞萌DX错误码0010深度解析及处理方法 - Chongxiの咖啡屋 做了一个明日方舟-奇象巡展的像素画拼豆工具 - Chongxiの咖啡屋 舞萌DX国服封禁机制详解 - Chongxiの咖啡屋 舞萌开机网络自检底层技术说明,断网如何排查讲解 - Chongxiの咖啡屋 舞萌机台开机初始化进程详解 - Chongxiの咖啡屋 为什么喜欢音乐 反而不该去学音乐? - Chongxiの咖啡屋 从装逼到嘉豪:中国互联网的精神胜利进化史 - Chongxiの咖啡屋 游蒋介石故居:奉化溪口 - Chongxiの咖啡屋 钢铁雄心4 steam正版导入全DLC补丁 - Chongxiの咖啡屋 漫漫长夜全地图及介绍 - Chongxiの咖啡屋 记一次无需实名换绑米哈游通行证手机号 - Chongxiの咖啡屋 邮储银行万事达借记卡全面指南 - Chongxiの咖啡屋 x402:一个来自27年前的状态码能救活被ai榨干的「人类网站」吗 - Chongxiの咖啡屋 舞萌国人口大普查:全服玩家数据分析 - Chongxiの咖啡屋 家中网络「捉奸」记 - Chongxiの咖啡屋 中国移动PT927G光猫折腾指南:破解超级密码改桥接 - Chongxiの咖啡屋 最好用的Android邮件客户端推荐 - Chongxiの咖啡屋 如何验证对方是不是Chongxi我本人 - Chongxiの咖啡屋 三星S20系列刷入移植OneUI8流程 - Chongxiの咖啡屋 使用obisidian和git插件来完美管理静态博客 - Chongxiの咖啡屋 玩客云拆机教程 - Chongxiの咖啡屋 母语级英语的本质,不是英语 - Chongxiの咖啡屋 我用过最好用的Android桌面(启动器) - Chongxiの咖啡屋 1. 区块链基本知识 - Chongxiの咖啡屋 b站创作激励提现几乎无门槛了 - Chongxiの咖啡屋 速报:APKPure 版 Telegram 被植入恶意后门 - Chongxiの咖啡屋
Ch.08:Go的运算符 - Chongxiの咖啡屋
Chongxi · 2026-05-15 · via Chongxiの咖啡屋

运算符是程序里最基础的计算工具。本篇会把 Go 的所有运算符过一遍,重点放在和其他语言不同的地方

算术运算符#

最基本的数学运算:

运算符含义示例
+1 + 2 = 3
-5 - 3 = 2
*3 * 4 = 12
/10 / 3 = 3
%取余10 % 3 = 1

简单吧,但是除法要注意下

整数除法直接截断:

PRTCL // GO

fmt.Println(10 / 3) // 3,不是 3.333...

fmt.Println(10.0 / 3) // 3.3333333333333335

两个整数相除,结果还是整数,小数部分直接丢掉。要得到小数结果,必须有一方是浮点数:

PRTCL // GO

a := 10

b := 3

fmt.Println(float64(a) / float64(b)) // 3.3333333333333335

取余的结果符号和被除数一致:

PRTCL // GO

fmt.Println(10 % 3) // 1

fmt.Println(-10 % 3) // -1,结果是负数

fmt.Println(10 % -3) // 1,结果是正数

取余结果的正负,跟被除数(左边那个数)一致,和除数(右边)无关

+ 用于字符串拼接:

PRTCL // GO

a := "Hello"

b := "Go"

fmt.Println(a + ", " + b + "!") // Hello, Go!

自增和自减#

Go 有 ++--,但和其他语言有个重要区别:

PRTCL // GO

a := 1

a++ // a = 2

a-- // a = 1

Go 的 ++-- 是语句,不是表达式,不能放在赋值右边:

PRTCL // GO

a := 1

b := a++ // ❌ 报错

也没有前置的 ++a

只有 a++a--,而且只能单独成行。Go 的设计去掉了 i++ + ++i 这类让人困惑的写法

赋值运算符#

基本赋值:

PRTCL // GO

a := 10

a = 20 // 重新赋值

复合赋值,把运算和赋值合在一起:

PRTCL // GO

a := 10

a += 5 // a = a + 5 = 15

a -= 3 // a = a - 3 = 12

a *= 2 // a = a * 2 = 24

a /= 4 // a = a / 4 = 6

a %= 4 // a = a % 4 = 2

字符串也可以用 +=

PRTCL // GO

s := "Hello"

s += ", Go!"

fmt.Println(s) // Hello, Go!

比较运算符#

比较运算符的结果是布尔值 truefalse

运算符含义
==等于
!=不等于
>大于
<小于
>=大于等于
<=小于等于

PRTCL // GO

fmt.Println(1 == 1) // true

fmt.Println(1 != 2) // true

fmt.Println(3 > 2) // true

fmt.Println(3 < 2) // false

只有相同类型才能比较:

PRTCL // GO

var a int = 1

var b int32 = 1

fmt.Println(a == b) // ❌ 报错,int 和 int32 不同类型

必须转换成同一类型再比较:

PRTCL // GO

fmt.Println(a == int(b)) // ✅ true

字符串比较按字典序:

PRTCL // GO

fmt.Println("abc" == "abc") // true

fmt.Println("abc" < "abd") // true,c < d

fmt.Println("abc" > "ab") // true,更长的字符串更大

浮点数比较要小心:

PRTCL // GO

a := 0.1 + 0.2

b := 0.3

fmt.Println(a == b) // false,精度问题

浮点数不能直接用 == 比较,应该判断差值是否足够小:

PRTCL // GO

import "math"

diff := math.Abs(a - b)

fmt.Println(diff < 1e-9) // true,认为相等

逻辑运算符#

用于组合多个布尔条件:

运算符含义示例
&&与,两边都为 true 才是 truetrue && false = false
||或,一边为 true 就是 truetrue || false = true
!非,取反!true = false

PRTCL // GO

age := 20

hasID := true

// 成年且有证件

if age >= 18 && hasID {

fmt.Println("pass")

}

// 是管理员或者是超级用户

isAdmin := false

isSuperUser := true

if isAdmin || isSuperUser {

fmt.Println("pass")

}

// 不是访客

isGuest := false

if !isGuest {

fmt.Println("not guess")

}

短路求值

&&|| 都有短路特性:

PRTCL // GO

// && 左边是 false,右边不会执行

false && someFunc() // someFunc() 不会被调用

// || 左边是 true,右边不会执行

true || someFunc() // someFunc() 不会被调用

利用这个特性可以避免空指针等问题:

PRTCL // GO

// 先检查 user 不为空,再访问 user.Name

if 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:

PRTCL // GO

fmt.Println(1 << 3) // 8,1 × 2³

fmt.Println(8 >> 1) // 4,8 ÷ 2

上一篇 iota 里定义文件大小就是用的左移:

PRTCL // GO

const (

_ = iota

KB = 1 << (10 * iota) // 1024

MB // 1048576

GB // 1073741824

)

按位与用来检查标志位:

PRTCL // GO

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 中清零:

PRTCL // GO

perm := PermRead | PermWrite // 011

// 去掉写权限

perm = perm &^ PermWrite // 001

fmt.Println(perm & PermWrite != 0) // false,写权限没了

其他语言一般用 a & ~b 实现同样效果,Go 的这个操作单独成一个运算符

运算优先级#

当一个表达式里有多个运算符时,优先级决定计算顺序。Go 的优先级从高到低:

优先级运算符
5(最高)* / % << >> & &^
4+ - | ^
3== != < <= > >=
2&&
1(最低)||

PRTCL // GO

fmt.Println(2 + 3*4) // 14,乘法优先

fmt.Println(2 > 1 && 3 > 2) // true,比较优先于 &&

不要依赖优先级,用括号写清楚:

PRTCL // GO

// 不清晰

result := a + b * c >> 2 & mask

// 清晰

result := ((a + (b * c)) >> 2) & mask

优先级规则不用背,遇到不确定的就加括号,清晰又不易错

运算符的一些细节#

^ 在 Go 里有两个用途

作为二元运算符是按位异或:

PRTCL // GO

fmt.Println(5 ^ 3) // 6,0101 ^ 0011 = 0110

作为一元运算符是按位取反(其他语言一般用 ~):

PRTCL // GO

var a uint8 = 5 // 00000101

fmt.Println(^a) // 250,11111010

整数除法和取余的关系

PRTCL // GO

a, b := 10, 3

q := a / b // 商 3

r := a % b // 余数 1

// 验证:q*b + r == a 永远成立

fmt.Println(q*b+r == a) // true

字符串不支持 -*/ 运算:

PRTCL // GO

"hello" - "world" // ❌ 报错

"hello" * 3 // ❌ 报错,Python 里可以但 Go 不行

字符串重复用 strings.Repeat()

PRTCL // GO

fmt.Println(strings.Repeat("go", 3)) // gogogo

下一篇讲 if 语句,条件判断的完整用法,以及 Go 里 if 特有的初始化语句写法