Zero dependencies. Text embedding. Disk persistence.

Vector similarity
in pure Go

Cosine, Euclidean, Manhattan. Text embedding. Disk persistence. Brute-force nearest-neighbor search. Zero allocations on distance computation. All pure Go.

main.go
package main

import "github.com/BackendStack21/go-vector/pkg/vector"

func main() {
    store := vector.NewStore(vector.CosineDistance)

    store.Add("cat", vector.Vector{1.0, 0.8, 0.1})
    store.Add("dog", vector.Vector{0.9, 0.7, 0.1})
    store.Add("car", vector.Vector{0.1, 0.0, 0.9})

    query  := vector.Vector{1.0, 0.9, 0.1}
    results := store.Search(query, 2)

    for _, r := range results {
        fmt.Printf("%s: %.4f\n", r.ID, r.Distance)
    }
    // cat: 0.0005
    // dog: 0.0026
}
0
dependencies
4
distance metrics
0
allocations per distance
96.8%
test coverage

Everything you need for
vector similarity

Ten vector operations, four distance metrics, and a production-ready in-memory vector store. All zero-allocation on read paths.

Vector Algebra

Dot product, norm, normalize, add, subtract, scale. Full suite of vector operations with zero-overhead []float32.

Distance Metrics

Cosine, Euclidean, Manhattan, Dot Product. Single-pass computation. Choose lower-is-better or higher-is-better sorting.

Vector Store

Add, get, remove, search. Top-K nearest-neighbor with any metric. Cloned outputs — no accidental mutation.

Text Embedding

Built-in Random Projections embedder (Johnson-Lindenstrauss). Bring your own OpenAI or Ollama adapter via the Embedder interface.

Disk Persistence

Gob-encode your store to disk. Full roundtrip with metric preservation. JSON export for debugging. ~60MB per 10K vectors at 1536d.

Minimal Surface

Standard library only. No CGo, no BLAS, no syscalls, no I/O. Compiles anywhere Go runs.

From text to vectors
in one call

Built-in Random Projections embedder using the Johnson-Lindenstrauss lemma. Deterministic, zero-dependency, ~10µs per document. Or bring your own via the Embedder interface.

Built-in: Random Projections

Sparse random projection matrix — each vocabulary token contributes to ~33% of output dimensions. Vocabulary built from your corpus. Output always L2-normalized.

rp := vector.NewRandomProjections(256)
rp.Fit(corpus)

v, _ := rp.Embed("machine learning")
// v is a 256-dim normalized Vector

Swap backends anytime

Implement the Embedder interface to plug in OpenAI, Ollama, or sentence-transformers. One method to implement per backend. Your search code never changes.

type Embedder interface {
    Embed(text string) (Vector, error)
    Dims() int
}

// OpenAIEmbedder, OllamaEmbedder, etc.
var emb vector.Embedder = NewOpenAIEmbedder()

Save. Load. Repeat.

Gob-encode your entire store to a file. Restore with metric and all data intact. JSON export for debugging and inspection.

Gob — compact and fast

Binary encoding via encoding/gob. Full roundtrip preserves IDs, vectors, and metric. ~200ms save for 10K vectors at 1536d.

store.Save("/data/vectors.db")

restored := vector.NewStore(...)
restored.Load("/data/vectors.db")
// all data + metric restored

JSON — human-readable

Export as indented JSON for debugging, inspection, or cross-language interop. Same roundtrip guarantees.

store.SaveJSON("/data/vectors.json")
restored.LoadJSON("/data/vectors.json")

Zero-allocation distance
computation

All benchmarks at 1536 dimensions (typical embedding size) on AMD EPYC. Single-pass Cosine and Euclidean — no intermediate vector allocations.

OperationLatencyAllocs
Dot7.5 µs0
Cosine9.4 µs0
Euclidean8.7 µs0
Manhattan9.4 µs0
Search 100 vectors3.2 ms63 KB
Search 1,000 vectors28.5 ms74 KB
Search 10,000 vectors315 ms185 KB

Brute-force search is O(n·d). Suitable for datasets up to ~100K vectors. Pair with an approximate index for larger scale.

Minimal attack surface

Pure float32 math. No CGo, no syscalls, no I/O, no network. Every edge case returns zero/nil — the library never panics.

SAFE Attack surface Pure float32 operations — no injection, no deserialization, no file access
SAFE Panic-free All edge cases (mismatched lengths, zero vectors, empty stores) return zero/nil
SAFE Memory hygiene Store outputs are always cloned. Internal state never leaks.
AWARE Float32 overflow Dot products of large vectors (>10⁵ dims with large magnitudes) can overflow. Normalize first.
AWARE Thread safety Store is read-safe but not write-safe concurrently. Guard with sync.Mutex.

Install

One import. Zero dependencies.

$ go get github.com/BackendStack21/go-vector
$ go test github.com/BackendStack21/go-vector/pkg/vector/ -cover