利用位运算设置参数

Wanjiongming 于 2019-10-29 发布

在使用 go 语言编程的过程中,经常会遇到如下的方法,利用位运算让某个函数只用一个参数达到多个参数才有的效果

log.SetFlags(log.LstdFlags | log.Lshortfile)
os.OpenFile("demo.txt", os.O_WRONLY|os.O_APPEND, os.ModePerm)

原理

其实这个和 Linux 中的权限表示很像,以 rwx(读写执行) 为例

r = 4 (0100)
w = 2 (0010)
x = 1 (0001)

可以每个权限数字都是 2 的 n 次幂,这样定义的原因是用二进制来表示只有一个 1。每位 1 代表一个权限,当进行或运算的时候,把其他权限的 1 加了进来,就代表有多个权限了

r|w = 6 (0110)
r|w|x = 7 (0111)

如何判断具有某个权限呢,如果把结果再与某个权限做与运算,当具有该权限时候,其他位都为 0,该权限位为 1,正好等于该权限的数值。所以如果与运算不为零或者结果和某个权限数值相等就代表具有该权限

6&r = 0100 == r != 0
6&w = 0010 == w != 0
6&x = 0000 == 0
6&(r|w) = 0110 == r|w

实现

这么有意思的技巧怎么应用在代码中呢,查看 log 包中的源码就清楚了

// 定义参数标记
// 这里又用到了 iota 进行递增赋值的技巧
const (
  Ldate         = 1 << iota
  Ltime
  Lmicroseconds
  Llongfile
  Lshortfile
  LUTC
  LstdFlags     = Ldate | Ltime
)

// 判断是否具有权限
if l.flag&(Lshortfile|Llongfile) != 0 {

}