運算子
- &:兩個位元都是 1,結果為 1,否則均為 0
- |:兩個位元其中有 1,結果為 1,否則均為 0
- ^:兩個位元相同,結果為 1,不同,結果為 0
& 運算子範例 + 解說
package main
import (
"fmt"
)
func main() {
result := 3
fmt.Print(result & 2) // 2
}
3 & 2 的結果為 2
3 的二進位表示是 0b0011
2 的二進位表示是 0b0010
從右到左,分別將兩個二進位表示的每一個位元做 & 運算
3 的二進位第一個位元為 1,2 的第一個位元為 0,結果為 0
3 的第二個位元為 1,2 的第二個位元為 1,結果為 1
兩者剩下的位元都為 0,不多贅述
0b0011
上下每個位元按位做 & 比較
0b0010
結果: 0b0010
運算的結果為 0b0010 換成十進位也就是 2。
| 運算子範例 + 解說
package main
import (
"fmt"
)
func main() {
result := 17
fmt.Print(result | 23) // 23
}
17 | 23 的結果為 23
17 的二進位表示是 0b10001
23 的二進位表示是 0b10111
從右到左,分別將兩個二進位表示的每一個位元做 | 運算
17 的二進位第一個位元為 1,23 的第一個位元為 1,結果為 1
17 的第二個位元為 1,23 的第二個位元為 0,結果為 0
0b10001
上下每個位元按位做 & 比較
0b10111
結果: 0b10111
依此類推,將結果組合起來為 0b10111,十進位表示就是 23。
場景運用
假設我們現在遇到的場景是,需要判斷一些事項是否有做過
一般來說普遍的作法,可能是設定一些變數來判定這些事項
var isHandleA = false
var isHandleB = false
var isHandleC = false
var isHandleD = false
缺點就是在不同的判斷式判斷不同的變數
我們可以將位元運算子運用在這種場景上,優雅的處理
var A = 1
var B = 2
var C = 4
var D = 8
var isHandled = 0
// 如果處理 C 了
isHandled = isHandled | C // 也可以簡寫成 isHandled |= C
if ((isHandled & C) != 0) // C就是有做過的
// 為甚麼是 1 2 4 8 ?
// 1的二進位 1
// 2的二進位 10
// 4的二進位 100
// 8的二進位 1000
// 這裡選的數字的二進位都是進一個位數的
// 舉例 D 跟 C 都有做過,所以 isHandled = 12
// 12 的二進位是 1100,所以當你要檢查 B 有沒有做過時
// 意思是 1100 & 0010 ,答案是0,所以 B 沒有做過
這樣子的寫法,或許在程式面感受不大,但試想如果你今天是有一些 Type 要存在 Database 裡
用位元運算子的寫法,只需要存一個 isHandled,其他的可以寫在程式面。