概要
Goでビット演算を利用したフラグ管理を行う実装を記述します。
複数指定可能なオプションを、constで定義している際などに使える便利な小技です。
Go以外でも、ビット演算を利用したオプション管理を実装している方は割と少なくないと思いますが、私自身これまでにビット演算を実装で使ったことがなく、「これは便利だわ〜」と感じたので、勉強ログ的なテンションで記述していきます。
ビット演算子
演算子 | 説明 |
---|---|
x | y | x と y の ビット論理和 |
x ^ y | x と y のビット排他的論理和 |
x & y | x と y のビット論理積 |
x << n | x の n ビット左シフト |
x >> n | x と n ビット右シフト |
実装
type AmazonPrimeOpt uint64
const (
Video AmazonPrimeOpt = 1 << iota
Music
Photos
Reading
Gaming
)
上記のようにオプションをconstで定義します。
Goでenumを作成する際に多く用いられるiota
を使用します。
上記constを二進数で表すと以下の定義になります。
Video = 1
Music = 10
Photos = 100
Reading = 1000
Gaming = 10000
これらの定数と論理和(|)や論理積(&)を使ってコードを書きます。
func main() {
// 組み合わせて設定
var opt AmazonPrimeOpt
opt = Photos | Reading
if opt & Photos != 0 {
fmt.Println("オプションに「Photos」が含まれています")
}
}
ビット演算の内訳は以下のような感じ
// `opt = Photos | Reading`
0100
+1000
------
1100
// `opt & Photos`
1100
*0100
------
0100
// `opt & Photos` ※Photosがオプションに含まれていなかった場合
1000 ・・・ オプションにPhotosが含まれないため、optの値は二進数で「1000」となる
*0100
------
0000 ・・・ 結果は0
まとめ
go/toolsの、ssa.BuilderModelsの実装を見るともっとわかりやすいですし、面白かったのでぜひ。
参考書籍