Go基礎之--位操作中你所不知道的用法

weixin_33858249發表於2017-12-04

之前一直忽略的就是所有語言中關於位操作,覺得用處並不多,可能用到也非常簡單的用法,但是其實一直忽略的是它們的用處還是非常大的,下面先回顧一下位操作符的基礎

位操作符

與操作:&
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 = 0
1 ^ 0 = 1
0 ^ 1 = 1
0 ^ 0 = 0

左移:<<
1 << 10 = 1024
1 << 20 = 1M
1 << 30 = 1G

右移:>>
1024 >> 10 = 1
1024 >>1 = 512
1024 >>2 = 256

 

關於上述知識的一個應用例項

可能這個例子在實際中用並不是特別嚴謹,但是也提供了我們寫程式碼的一種思路

這裡拿微博或者qq使用者的特權為例子:
一個qq號可以用VIP會員,SVIP超級會員,藍鑽使用者,黃鑽使用者,紅鑽使用者....
我們通常的想法可能是如果資料庫中儲存自己會給使用者存這個欄位表示這個使用者開通了哪些特權
我們在程式碼中的寫法可能也是如下所示:

 1 package main
 2 
 3 import (
 4     "fmt"
 5 )
 6 
 7 type users struct {
 8     name   string
 9     flag   uint8
10     vip    bool
11     svip   bool
12     blue   bool
13     red    bool
14     yellow bool
15 }
16 
17 func setVip(user users) users {
18     user.vip = true
19     return user
20 }
21 
22 func isVip(user users) {
23     if user.vip {
24         fmt.Println("user is vip")
25     } else {
26         fmt.Println("user is not vip")
27     }
28 }
29 
30 func binaryTest() {
31     var user users
32     user.name = "test01"
33     user.vip = true
34     isVip(user)
35     user.vip = false
36     isVip(user)
37 }
38 
39 func main() {
40     binaryTest()
41 
42 }

這種實現方式也可以,但是明顯我們需要為每個型別都做操作,並且如果以後又有更多的各種各樣的會員和鑽有需要新增新的,所以並不是最佳方法,下面我們通過位操作來實現上述的功能,程式碼如下:

 1 package main
 2 
 3 import (
 4     "fmt"
 5 )
 6 
 7 type users struct {
 8     name string
 9     flag uint8
10 }
11 
12 // 這裡通過位移的方式預設00000 從左邊一次為vip,svip,blue,red,yellow
13 const (
14     vip   = 1
15     svip  = (1 << 1)
16     blue  = (1 << 2)
17     red   = (1 << 3)
18     yello = (1 << 4)
19 )
20 
21 // setFlag 用於設定使用者開通了哪些特權
22 func setFlag(user users, isSet bool, typeFlag uint8) users {
23     if isSet == true {
24         user.flag = user.flag | typeFlag
25     } else {
26         user.flag = user.flag ^ typeFlag
27     }
28     return user
29 }
30 
31 //isFlag 用於判斷使用者是否開通某項特權
32 func isFlag(user users, typeFlag uint8) bool {
33     result := user.flag & typeFlag
34     return result == typeFlag
35 }
36 
37 func binaryTest() {
38     var user users
39     user.name = "coder"
40     user.flag = 0
41 
42     //判斷使用者是否是vip
43     result := isFlag(user, vip)
44     fmt.Printf("user is Vip:%t\n", result)
45 
46     //給使用者開通vip,並看使用者是否開通vip
47     user = setFlag(user, true, vip)
48     result = isFlag(user, vip)
49     fmt.Printf("user is Vip:%t\n", result)
50 
51     //取消使用者的vip,並檢視使用者是否還是vip
52     user = setFlag(user, false, vip)
53     result = isFlag(user, vip)
54     fmt.Printf("user is Vip:%t\n", result)
55 }
56 
57 func main() {
58     binaryTest()
59 }

上面程式碼就是一種位運算一種非常巧妙的用法,當新新增各種特權的時候只需要在最開始定義的常亮那裡新增一行程式碼即可,就可以直接實現對這種特權的設定和取消,以及檢視是否開通。

所有的努力都值得期許,每一份夢想都應該灌溉!

相關文章