Memory efficient
Roughly one bit of storage per element — orders of magnitude smaller than a hash map of booleans, with cache-friendly word layout.
Go library · BSD-style license
A compact, high-performance mapping between non-negative integers and boolean
values — far leaner than map[uint]bool. Set, clear, flip, test,
and run union / intersection / difference at native speed.
go get github.com/bits-and-blooms/bitset
var b bitset.BitSet
b.Set(10).Set(11).Set(1000)
if b.Test(11) {
fmt.Println("bit 11 is set")
}
// rich set algebra
hits := b.Intersection(other).Count()
// iterate set bits (Go 1.23+)
for i := range b.EachSet() {
fmt.Println("set:", i)
}
Why bitset
Roughly one bit of storage per element — orders of magnitude smaller than a hash map of booleans, with cache-friendly word layout.
Union, intersection, difference, symmetric difference and complement — each with in-place and cardinality-only variants.
Set, Clear, and Flip return the bitset, so mutations read naturally: b.Set(10).Set(11).
Walk set or clear bits with NextSet / NextClear, or range over EachSet() on Go 1.23+.
WriteTo / ReadFrom give a stable byte layout across platforms, plus MarshalBinary and JSON support.
Fuzz-tested and used in production by databases, search engines, blockchains and CNCF projects worldwide.
Quick start
go get github.com/bits-and-blooms/bitset
package main
import (
"fmt"
"math/rand"
"github.com/bits-and-blooms/bitset"
)
func main() {
var b bitset.BitSet
// play some Go Fish
for i := 0; i < 100; i++ {
card1 := uint(rand.Intn(52))
card2 := uint(rand.Intn(52))
b.Set(card1)
if b.Test(card2) {
fmt.Println("Go Fish!")
}
b.Clear(card1)
}
// chaining
b.Set(10).Set(11)
for i, e := b.NextSet(0); e; i, e = b.NextSet(i + 1) {
fmt.Println("the following bit is set:", i)
}
if b.Intersection(bitset.New(100).Set(10)).Count() == 1 {
fmt.Println("intersection works.")
}
}
Serialization
Serialize a bitset to a stable, platform-independent stream of bytes with
WriteTo, then read it back with ReadFrom — which
reuses the existing instance to minimize allocations.
Performance tip: wrap files and network connections in
bufio readers and writers for the best throughput.
bs := bitset.New(9585)
for i := uint(0); i < 9585; i += 97 {
bs = bs.Set(i)
}
// write
var buf bytes.Buffer
n, err := bs.WriteTo(&buf)
// read back into an existing bitset
bs = bitset.New()
n, err = bs.ReadFrom(&buf)
In production
Part of the awesome-go collection and depended on across databases, search, blockchain and infrastructure.
…and many more across the Go ecosystem.
A bitset of N bits uses at least N/8 bytes and grows to fit the
largest index you touch. For very large, sparse sets, consider compressed
Roaring bitmaps — you can convert
freely between the two.
Go deeper
Want to write Go like the code behind bitset? This book takes you from solid testing practices all the way to squeezing real performance out of Go — the same techniques used to keep this library fast.
Get the book on Amazon ↗