Golang位操作
之前学习语言一直忽略的就是所有语言中关于位操作,觉得用处并不多,可能用到也非常简单的用法,但是其实它们的作用还是非常大的。以下是一些Golang位操作符的基础:
与操作: &
1 & 1 = 1
1 & 0 = 0
0 & 1 = 0
0 & 0 = 0
或操作: |
1 | 1 = 1
1 | 0 = 1
0 | 1 = 1
0 | 0 = 0
异或: ^
1 ^ 1 = 1
1 ^ 0 = 1
0 ^ 1 = 1
0 ^ 0 = 0
左移: <<
1 << 10 = 1024
1 << 20 = 1M
1 << 30 = 1G
右移: >>
1024 >> 10 = 1
1024 >> 1 = 512
1025 >> 2 = 256
关于上述的例子可能在实际的运算中并不是十分的严谨,但是也为我们的业务实现提供了一种思路。
这里拿优酷土豆会员的特权举个例子:
一个优酷账号可以为体验会员、白银会员、黄金会员、酷喵会员…
我们常用的做法就是数据库中存储这个字段表示这个用户开通了哪些特权,如以下代码所示:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
| package main
import ( "fmt" )
type users struct { name string flag uint8 privilege }
type privilege struct { vip bool experience bool silver bool gold bool cool bool }
func setVip(user users) users { user.vip = true return user }
func isVip(user users) { if user.vip { fmt.Println("user is vip") } else { fmt.Println("user is not vip") } }
func binaryTest() { var user users user.name = "test01" user.vip = true isVip(user) user.vip = false isVip(user) }
func main() { binaryTest() }
|
这种实现方式也可以,但是明显我们需要为每个类型都做操作,并且如果以后又有更多的各种各样的会员有需要添加新的,所以并不是最佳方法,下面我们通过位操作来实现上述的功能,代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56
| package main
import ( "fmt" )
type users struct { name string flag uint8 }
const ( vip = 1 experience = (1 << 1) silver = (1 << 2) gold = (1 << 3) cool = (1 << 4) )
func setFlag(user users, isSet bool, typeFlag uint8) users { if isSet == true { user.flag = user.flag | typeFlag } else { user.flag = user.flag ^ typeFlag } return user }
func isFlag(user users, typeFlag uint8) bool { result := user.flag & typeFlag return result == typeFlag }
func binaryTest() { var user users user.name = "gopher" user.flag = 0 result := isFlag(user, vip) fmt.Printf("user is Vip: %t\n", result) user = setFlag(user, true, vip) result = isFlag(user, vip) fmt.Printf("user is Vip: %t\n", result) user = setFlag(user, false, vip) result = isFlag(user, vip) fmt.Printf("user is Vip: %t\n", result) }
func main() { binaryTest() }
|
上面代码一种非常常见的用法,当新添加各种特权的时候只需要在最开始定义的常亮那里添加一行代码即可,就可以直接实现对这种特权的设置和取消,以及查看是否开通。