go语言位操作库 — bitset
bitset库
实现了bitsets
数据结构,这是一种正整数和布尔值映射关系的结构,它比map[uint]bool
更高效
什么是bitsets✦
bitsets基本思想是用一个bit位来标记某个元素对应的Value,每一位表示一个数,1表示存在,0表示不存在 比如我要表示1, 3, 7这3个数
- 构造一个空白bitsets:00000000
- 每位代表的值如下:76543210
- 想要表示的值标记1:10001010
有什么好处?✦
最大的好处是节省存储空间,假设有20亿个正整数中找出m是否在其中 如果每个数字用int存储,占8byte,2000000000 * 8 = 14G 如果用bit存储每个数字,占1bit,2000000000 / 8 = 0.233G 由此可见bitsets节省了极大的存储空间
Usage✦
安装
go get github.com/bits-and-blooms/bitset
基本操作
// 构造一个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
指定位置操作
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
两个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
遍历
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