go中位运算符是系统编程必备工具,用于高效提取字节字段、判断标志位、实现位反转等;需注意运算符优先级、掩码写法及msb/lsb位序约定。

&、|、^、&^、、<code>>> 这六个运算符不是“炫技工具”,而是 Go 中处理整数状态、协议字段和性能关键路径的默认语言。不掌握它们,等于在系统层编程中主动放弃一半表达力。
提取字节内某几位字段时,别用 if 判断位偏移
读取嵌入式协议或网络包时,常见一个 uint8 里打包了多个字段(比如前3位是 type,后5位是 id)。错误做法是写一堆 if n >= 5 { ... };正确做法是统一用位移+掩码:
- 取高3位:
(b >> 5) & 0x07(右移5位,再与0b00000111掩码) - 取低5位:
b & 0x1F(直接与0b00011111掩码) - 注意:Go 的
&优先级低于+和-,但高于==;写a & b == 0实际等价于a & (b == 0),必须加括号:(a & b) == 0
判断权限或标志位是否启用,用 & 而非 ==
定义权限常量时用 1 是标准姿势,但检查时容易错写成 <code>userPerm == ReadPermission。这会漏掉组合权限(如同时有读+写)。
- 正确:使用
userPerm & ReadPermission != 0 - 清掉某权限:用
userPerm &^ WritePermission(&^是 Go 特有,比userPerm & (^WritePermission)更安全,避免符号扩展问题) - 翻转某权限:用
userPerm ^= ExecutePermission
跨字节字段拼接时,别用 int 当中转类型
解析 12-bit 时间戳或 10-bit ADC 值时,字段可能横跨两个字节(比如起始位是第 6 位,共 12 位)。此时若用 int 存中间值,负数右移会高位补 1,结果全毁。
- 始终用无符号类型:
uint64最稳妥(足够容纳 32 位字段+位移余量) - 典型拼接逻辑:
val := uint64(data[startByte]) ,再按需右移+掩码 - 务必先检查
len(data) > startByte+1,否则 panic
反转 32 位整数的二进制位序,别循环逐位构造
循环反转 32 位要 32 次迭代+分支,而分治位翻转只需 5 行位操作,无分支、无循环、CPU 友好。
- 核心模式:交换相邻 1 位 → 相邻 2 位 → 相邻 4 位 → 相邻 8 位 → 相邻 16 位
- 例如第一步(交换相邻 1 位):
x = ((x & 0x55555555) > 1) - 完整实现见
math/bits.Reverse32(Go 1.9+ 标准库已内置),但理解其原理才能调试自定义协议
实际中最容易被忽略的,是字节序和位序的隐含约定:MSB-first 还是 LSB-first?协议文档没写清楚时,data[n/8] & (1 和 <code>data[n/8] & (1 会给出完全相反的结果。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











