Go中&&和||优先级低于==、!=等比较运算符,而位运算符&、|、^优先级介于比较与逻辑之间;赋值运算右结合但不支持链式;++/--仅为语句不可用于表达式。

Go 里 && 和 || 比 ==、!= 优先级高?错的
这是最常被误记的一点:很多人凭 C/Java 经验以为逻辑与/或优先级高于比较,但在 Go 中,&& 和 || 的优先级**低于**所有比较运算符(==、!=、、>= 等)。这意味着 a == b && c != d 不需要括号也能按预期分组,但一旦混入位运算或赋值,就容易翻车。
真正危险的是和 &、|、^ 这些位运算符混用——它们的优先级比 && 高,但比 == 低。比如:
if a & b == c { ... }这实际等价于 if a & (b == c) { ... },而 b == c 是布尔值,不能参与位与,编译直接报错:invalid operation: a & (b == c) (mismatched types int and bool)。
- 遇到
&、|、^和比较运算符共存,必须加括号明确意图,如(a & b) == c -
&&/||可以放心和比较连写,无需括号;但和位运算、移位(、>>)一起时,务必查优先级表 - Go 官方优先级共 5 级,其中位运算(
&、^、|)和算术运算同级(第 4 级),比较是第 3 级,逻辑是第 2 级
赋值运算符 =、+= 的右结合性容易引发误解
Go 中赋值是右结合的,a = b = c 合法吗?不合法——因为 b = c 返回的是 c 的值,但 a = (b = c) 要求 b = c 有可寻址结果,而它只是语句,不是表达式。所以 a = b = c 编译失败:cannot assign to b = c。
立即学习“go语言免费学习笔记(深入)”;
但复合赋值如 a += b += c 更隐蔽:
a, b, c := 1, 2, 3 a += b += c // 编译错误:invalid operation: b += c (no addressable left-hand side)
原因:复合赋值要求左操作数必须是“可寻址的”(addressable),而 b += c 本身不是变量,无法作为 a += ... 的右操作数。
- Go 不支持链式赋值,
x = y = z或x += y += z全部非法 - 若想模拟,必须拆成两行:
y += z; x += y - 注意
:=是声明+赋值,不能出现在表达式中,f(x := 1)直接语法错误
++ 和 -- 不是运算符,不能用于表达式
Go 里 ++ 和 -- 是语句,不是表达式级运算符。这意味着你不能写 a = b++、if x-- > 0 或 arr[i++] = v —— 全部编译报错:syntax error: unexpected ++ 或 cannot use x-- as value。
常见误写场景:
// ❌ 错误
for i := 0; i < len(s); i++ {
if s[i++] == 'a' { ... } // i++ 是语句,不能在索引中用
}
// ✅ 正确写法:先用再加,或后加再用
for i := 0; i < len(s); i++ {
if s[i] == 'a' { ... }
i++ // 显式写,但通常应靠 for 自增控制
}
-
++/--只能单独成句,后面不能跟分号以外的符号 - 函数调用参数、数组索引、返回值位置等一切需要“值”的地方,都不能出现
++/-- - 想实现类似 C 的效果,必须拆成两步:
val := arr[i]; i++
类型断言 .(T) 和方法调用 .Method() 的结合顺序
当对一个接口值做类型断言后再调用方法,比如 obj.(Stringer).String(),看起来没问题,但若 obj 实际不是 Stringer,运行时 panic。更隐蔽的问题是结合了逻辑运算:
if obj.(Stringer).String() != "" && obj != nil { ... }这段代码会在 obj 不是 Stringer 时直接 panic,根本不会执行 obj != nil 判断——因为 . 的优先级高于 &&,整个左边先求值。
- 类型断言失败是运行时 panic,无法用
&&短路规避 - 安全写法是先用「带 ok 的断言」:
if s, ok := obj.(Stringer); ok && s.String() != "" - 记住:
.(成员访问)、->(C 风格)、[](索引)、()(调用)都是最高优先级,且左结合;它们会最先绑定
Go 的运算符优先级表很短,但出错往往不在“记不住”,而在“凭经验套其他语言”。尤其位运算、赋值、类型断言这几处,编译器报错信息未必直指根源,得看清楚哪部分被优先绑定了。










