Go library · BSD-style license

Bitsets, done fast in Go.

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
main.go
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)
}
1 bitper element
60+methods
SIMDaccelerated
Go 1.16+supported

Why bitset

Everything you need to push bits around

Memory efficient

Roughly one bit of storage per element — orders of magnitude smaller than a hash map of booleans, with cache-friendly word layout.

🧮

Full set algebra

Union, intersection, difference, symmetric difference and complement — each with in-place and cardinality-only variants.

🔗

Chainable API

Set, Clear, and Flip return the bitset, so mutations read naturally: b.Set(10).Set(11).

🔁

Fast iteration

Walk set or clear bits with NextSet / NextClear, or range over EachSet() on Go 1.23+.

💾

Portable serialization

WriteTo / ReadFrom give a stable byte layout across platforms, plus MarshalBinary and JSON support.

🚀

Battle-tested

Fuzz-tested and used in production by databases, search engines, blockchains and CNCF projects worldwide.

Quick start

From zero to bits in seconds

1

Install

go get github.com/bits-and-blooms/bitset
2

Use it

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

Save and restore, portably

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.

Full API reference ↗
serialize.go
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

Trusted by demanding systems

Part of the awesome-go collection and depended on across databases, search, blockchain and infrastructure.

…and many more across the Go ecosystem.

Working with billions of bits?

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.

Roaring for Go ↗
Mastering Programming: From Testing to Performance in Go — book cover

Go deeper

Mastering Programming:
From Testing to Performance in Go

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 ↗