比 && 先算;go中算术运算符优先级高于比较运算符,比较运算符又高于位运算符,逻辑运算符 && 和 || 优先级最低。

Go 里 + 和 && 谁先算?别靠猜,看这张表就够了
Go 不支持自定义运算符优先级,所有规则硬编码在语言规范里。实际写代码时出错,往往不是记不住,而是没意识到某些组合根本不会按你脑补的顺序执行——比如 a & b == c 实际等价于 a & (b == c),而不是 (a & b) == c,因为 == 比 & 优先级高。
-
==、!=、、<code>>等比较运算符,优先级高于位运算&、^、|,但低于算术运算+、- - 逻辑与
&&和逻辑或||是最低的(除了赋值和逗号),比所有比较、位、算术都低 - 唯一需要强制加括号的常见场景:混合位运算和比较,比如想判断
(flags & mask) != 0,漏括号就成flags & (mask != 0),类型都不匹配
^ 是异或不是幂运算,** 在 Go 里根本不存在
从 Python 或 JS 切过来的人容易在这栽跟头:^ 在 Go 里永远是按位异或,不是幂运算;Go 压根没有 ** 运算符。想算 2 的 10 次方?得用 math.Pow(2, 10),或者整数场景下手写位移(1 )。
-
^和&、|同级,左结合,a ^ b & c等价于a ^ (b & c) - 位移运算符
、<code>>>优先级高于+、-,所以1 是 <code>1 ,不是 <code>(1 - 负数右移行为依赖符号位扩展,
-8 >> 1得到的是-4,不是2147483644(无符号右移要用uint类型)
复合赋值里的优先级陷阱:a += b 不等于 <code>a = a + (b ?
它等于。Go 规定所有复合赋值(+=、&=、^= 等)右边的表达式都自动整体括起来,再代入左边。所以 a += b 等效于 <code>a = a + (b ,不是 <code>(a + b) 。这点比 C 安全,但容易误以为“既然有 <code>+=,那右边肯定先算”,其实只是语法糖保证了括号。
-
a &= b == c等效于a = a & (b == c),但b == c返回bool,而&要求两边都是整数,直接编译报错:invalid operation: a & (b == c) (mismatched types int and bool) - 复合赋值不改变运算符本身优先级,只包一层括号;真正要避免错误,还是得主动加括号让意图清晰,尤其涉及混合类型时
- 性能上无差异,编译器会优化掉多余括号,但可读性差的表达式会让审查者多盯三秒
调试时怎么看实际执行顺序?用 go tool compile -S 看汇编不现实,试试这个办法
与其背表,不如让编译器告诉你它怎么理解。最轻量的办法:把可疑表达式单独拎出来,加个打印或断点,观察中间值。比如不确定 a | b == c & d 怎么分组,就拆成两行:
立即学习“go语言免费学习笔记(深入)”;
tmp1 := b == c tmp2 := c & d fmt.Println(a | tmp1, tmp2) // 编译直接失败,立刻暴露类型错配
更稳的路子是写单元测试,覆盖边界值:
- 用
int8(1) & int8(2) == 0测试是否被当成(1 & 2) == 0(是,结果 true) - 换成
int8(1) & int8(2) == int8(1),结果 false,说明确实是先算&再比== - 如果表达式含函数调用,比如
f() + g() && h(),注意&&是短路的,h()可能根本不执行
优先级表可以查,但人脑缓存有限;真正在意顺序的地方,加括号成本极低,省下的 debug 时间远超多敲两个字符。









