go 語言位操作庫 bitset

wuyunhua發表於2022-01-02

bitset庫實現了bitsets資料結構,這是一種正整數和布林值對映關係的結構,它比map[uint]bool更高效

什麼是 bitsets

bitsets 基本思想是用一個 bit 位來標記某個元素對應的 Value,每一位表示一個數,1 表示存在,0 表示不存在 比如我要表示 1, 3, 7 這 3 個數

  1. 構造一個空白 bitsets:00000000
  2. 每位代表的值如下:76543210
  3. 想要表示的值標記 1:10001010

有什麼好處?

最大的好處是節省儲存空間,假設有 20 億個正整數中找出 m 是否在其中 如果每個數字用 int 儲存,佔 8byte,2000000000 * 8 = 14G 如果用 bit 儲存每個數字,佔 1bit,2000000000 / 8 = 0.233G 由此可見 bitsets 節省了極大的儲存空間

Usage

  1. 安裝
go get github.com/bits-and-blooms/bitset
  1. 基本操作
// 構造一個64bit長度的bitset
b := bitset.New(64)
// 放入一個數
b.Set(10)
fmt.Println(b.DumpAsBits()) // 000000000000000000000000000000000000000000000000010000000000
// 刪除一個值
b.Clear(10)
fmt.Println(b.DumpAsBits()) // 000000000000000000000000000000000000000000000000000000000000
// 長度
b.Set(1).Set(3)
fmt.Println(b.Len()) // 64
// 測試
fmt.Println(b.Test(3)) // true
fmt.Println(b.Test(4)) // false
  1. 指定位置操作
b := &bitset.BitSet{}
b.Set(3)
// 在指定位置插入0
b.InsertAt(3)
fmt.Println(b.DumpAsBits()) // 000000000000000000000000000000000000000000000000000000010000
// 在指定位置修改
b.SetTo(4, false)
fmt.Println(b.DumpAsBits()) // 000000000000000000000000000000000000000000000000000000000000
// 指定位置刪除
b.Set(3).DeleteAt(3) // 000000000000000000000000000000000000000000000000000000000000
  1. 兩個 bitsets 互動
a := &bitset.BitSet{}
a.Set(1).Set(3).Set(5)
b := &bitset.BitSet{}
b.Set(3).Set(5).Set(7)
// 交集
fmt.Println(a.Intersection(b)) // {3,5}
// 並集
fmt.Println(a.Union(b)) // {1,3,5,7}
// 差集
fmt.Println(a.Difference(b)) // {1}
// 全等
fmt.Println(a.Equal(b)) // false
  1. 遍歷
b := bitset.New(64)
b.Set(1).Set(3).Set(5).Set(7)
for i, e := b.NextSet(0); e; i, e = b.NextSet(i + 1) {
    fmt.Println("The following bit is set:", i)
}
// The following bit is set: 1
// The following bit is set: 3
// The following bit is set: 5
// The following bit is set: 7

一個例子

假設現在資料庫裡有一個欄位儲存使用者狀態,設計是這樣的:0 00 00

第 1、2 位表示會員等級 00 表示普通會員,01 表示 vip1,10 表示 vip2,11 表示 svip

第 3、4 位表示頭像狀態 00 表示未上傳,01 表示 01 稽核中,10 稽核失敗,11 稽核通過

第 5 位表示賬號狀狀態 0 表示正常,1 表示封禁

b := bitset.New(5)
// 設定vip1,第1位0,第2位1
b.SetTo(1, false).SetTo(2, true)

// 設定頭像稽核失敗,第3位1,第4位0
b.SetTo(3, true).SetTo(4, false)

// 狀態初始化
b.ClearAll()

// 檢視賬號狀態,第5位,true代表1 false代表0
b.Test(5) 

// 是不是svip,第1、2位是11
b.Test(1) && b.Test(2)

總結

bitset/bitmap 在日常開發中會經常用到,在特定場景下有很好的效果。這個庫可以簡化操作 bitset/bitmap 的難度,而且這個庫的原始碼也很好的演示了 go 的位操作

官方文件:https://github.com/bits-and-blooms/bitset

更多原創文章乾貨分享,請關注公眾號
  • go 語言位操作庫 bitset
  • 加微信實戰群請加微信(註明:實戰群):gocnio

相關文章