go语言位运算
一、6 种位运算符及用途
运算符 | 语法 | 功能 | 典型应用场景 |
---|---|---|---|
& | a & b | 按位与 | 掩码操作、判断奇偶、权限检查 |
| | a | b | 按位或 | 合并标志位、设置权限 |
^ | a ^ b | 按位异或 | 交换变量、数据加密、去重 |
&^ | a &^ b | 位清空(AND NOT) | 清除指定标志位 |
<< | a << n | 左移 | 快速乘2ⁿ、位掩码生成 |
>> | a >> n | 右移 | 快速除2ⁿ、提取高位数据 |
💡 关键:
- ^ 作为单目运算符时表示按位取反(如 ^0b1010 = 0b0101)
- &^ 是 Go 特有操作:结果为 a & (^b)
二、4 类实战应用
1. 高效状态管理(权限系统)
const (Read = 1 << iota // 0b001 (1)Write // 0b010 (2)Execute // 0b100 (4)
)// 添加权限:user |= Read | Write
// 检查权限:(user & Read) != 0
// 清除权限:user &^= Write
2. 算法优化(高频题目)
-
判断奇偶:n & 1 == 0 比 n % 2 == 0 快 3~5 倍
-
交换变量(无临时变量):
a ^= b
b ^= a
a ^= b
-
2 的幂判断:n & (n-1) == 0
-
只出现一次的数字(LeetCode 136):
func singleNumber(nums []int) int {result := 0for _, num := range nums {result ^= num // 利用 a ^ a = 0 的性质}return result
}
3. 内存压缩(位图 Bitmap)
type Bitmap struct {bits []uint64
}// 设置第 n 位为 1
func (b *Bitmap) Set(n int) {index, offset := n/64, uint(n%64)b.bits[index] |= 1 << offset
}// 检查第 n 位
func (b *Bitmap) Get(n int) bool {index, offset := n/64, uint(n%64)return (b.bits[index] & (1 << offset)) != 0
}
海量数据去重、快速检索(10亿数据仅需 125MB 内存)
4. 数据编解码
IP 地址转换:
ip := 0xC0A80101 // 192.168.1.1
part1 := byte(ip >> 24) // 192
part2 := byte(ip >> 16) // 168
三、避坑指南
1. 运算符优先级问题
❌ 错误写法:
if flags & Read != 0 { ... } // 等价于 flags & (Read != 0)
✅ 正确写法:
if (flags & Read) != 0 { ... } // 必须加括号!
2. 移位溢出
var a uint8 = 255
b := a << 1 // 结果为 254(而非 510),uint8 溢出
移位长度不能超过类型位数(如 int32 最多移 31 位)
3. 负数右移
var a int8 = -8 // 二进制: 11111000
b := a >> 2 // 结果: -2 (11111110)
右移负数时高位补 1(符号位扩展)
四、性能优化证据
操作 | 位运算实现 | 传统实现 | 性能提升 |
---|---|---|---|
乘 2 | n << 1 | n * 2 | 3~5 倍 |
除 2(向下取整) | n >> 1 | n / 2 | 2~4 倍 |
奇偶判断 | n & 1 | n % 2 | 4~6 倍 |
取模 2 k 2^k 2k | n & (k-1) | n % k | 10 倍+ |
⚠️ 注意:现代编译器可能自动优化简单算术,但位运算在复杂表达式和底层系统中仍具优势。
五、灵魂问题
-
Q:x & (x-1) 有什么深层用途?
A:
判断是否为 2 的幂(结果为 0 则是)
计算二进制中 1 的个数(循环直到 0)
求最低位的 1(x & ^(x-1)) -
Q:如何用位运算实现加法?
A:
func add(a, b int) int {for b != 0 {carry := a & b // 计算进位a = a ^ b // 无进位加法b = carry << 1 // 进位左移}return a
}
六、真题
题目:实现函数 func reverseBits(num uint32) uint32(翻转二进制位)
答案:
func reverseBits(num uint32) uint32 {result := uint32(0)for i := 0; i < 32; i++ {// 取 num 的最低位,放到 result 的对应高位result = (result << 1) | (num & 1)num >>= 1}return result
}
💡 注意点:
- 明确位运算优先级(用括号避免歧义)
- 处理负数时说明符号位行为
- 强调位运算在内存敏感场景(嵌入式/高频交易)的价值