The fastest, most feature-rich caching library for Go
Features β’ Quick Start β’ API β’ Policies β’ Benchmarks β’ Examples
- π Blazing fast β Sub-microsecond Get/Set, sharded design, lock striping
- 𧬠Full generics β Type-safe API with
Cache[K, V], nointerface{} - π Thread-safe β Zero data races under
-race, tested with 100K+ goroutines - π 7 eviction policies β LRU, LFU, FIFO, Random, Clock, ARC, TinyLFU
- β±οΈ TTL support β Per-key TTL, Touch, auto-cleanup, expiration callbacks
- π Atomic operations β GetOrSet, Compute, CAS, Increment, Decrement
- π‘ Metrics β Prometheus, OpenTelemetry, JSON β zero external deps
- πΎ Persistence β Save/Load/Snapshot with JSON, Gob, compressed formats
- π― Zero allocations β sync.Pool, pre-computed hashes, cache-line padding
- π Extensible β Middleware, events, custom hashers, pluggable serializers
go get github.com/gocachex/gocachexRequires Go 1.24+ | Zero external dependencies in core
package main
import (
"fmt"
"time"
"github.com/gocachex/gocachex"
"github.com/gocachex/gocachex/policy"
)
type User struct {
ID int
Name string
}
func main() {
// Create a cache with LRU eviction, 5-minute TTL, max 100K entries.
cache := gocachex.New[string, User](
gocachex.WithTTL[string, User](5 * time.Minute),
gocachex.WithPolicy[string, User](policy.LRU),
gocachex.WithMaxEntries[string, User](100_000),
)
defer cache.Close()
// Set with default TTL.
cache.Set("user:1", User{ID: 1, Name: "Alice"})
// Set with custom TTL.
cache.Set("user:2", User{ID: 2, Name: "Bob"}, 10*time.Minute)
// Get.
if user, ok := cache.Get("user:1"); ok {
fmt.Printf("Found: %+v\n", user)
}
// Atomic GetOrSet.
user, loaded := cache.GetOrSet("user:3", User{ID: 3, Name: "Charlie"})
fmt.Printf("User: %+v (loaded from cache: %v)\n", user, loaded)
// Lazy loading with singleflight.
user, err := cache.GetOrLoad("user:4", func(key string) (User, error) {
return User{ID: 4, Name: "Diana"}, nil // e.g., fetch from database
})
// Stats.
stats := cache.Stats()
fmt.Printf("Hit ratio: %.2f%%\n", stats.HitRatio*100)
}| Method | Description |
|---|---|
New[K, V](opts...) |
Create a new cache |
Get(key) |
Retrieve a value |
Set(key, value, ttl...) |
Insert or update |
Delete(key) |
Remove an entry |
Has(key) |
Check existence |
Clear() |
Remove all entries |
Len() |
Entry count |
Keys() |
All keys (snapshot) |
Values() |
All values (snapshot) |
Range(func) |
Iterate entries |
Close() |
Shutdown + cleanup |
| Method | Description |
|---|---|
Set(key, val, ttl) |
Per-key TTL |
Touch(key) |
Reset TTL |
TTL(key) |
Remaining TTL |
Cleanup() |
Manual sweep |
WithTTL(d) |
Default TTL |
WithOnExpired(fn) |
Expiration callback |
| Method | Description |
|---|---|
GetOrSet(key, val) |
Get existing or set new |
Compute(key, fn) |
Read-modify-write |
CompareAndSwap(key, old, new, cmp) |
Conditional swap |
Swap(key, val) |
Replace and return old |
Replace(key, val) |
Replace if exists |
Increment(cache, key, delta) |
Atomic increment |
Decrement(cache, key, delta) |
Atomic decrement |
GetOrLoad(key, loader) |
Lazy load with singleflight |
// Range-over-func (Go 1.23+)
for key, value := range cache.All() {
fmt.Println(key, value)
}
// Snapshot iterator
it := cache.NewSnapshotIterator()
for it.Next() {
key, value := it.Value()
fmt.Println(key, value)
}
// Concurrent iteration (parallel across shards)
cache.ConcurrentRange(func(key string, value int) bool {
process(key, value)
return true
})| Policy | Algorithm | Best For |
|---|---|---|
| LRU | Doubly-linked list + hashmap | General workloads |
| LFU | Frequency buckets with aging | Popularity-driven access |
| FIFO | Insertion-order queue | Simple, predictable eviction |
| Random | Random selection | Lowest overhead |
| Clock | Second-chance circular buffer | LRU approximation, less overhead |
| ARC | Adaptive 4-list (T1/T2/B1/B2) | Self-tuning recency vs frequency |
| TinyLFU | Count-Min Sketch + SLRU | Best hit ratio for most workloads |
cache := gocachex.New[string, int](
gocachex.WithPolicy[string, int](policy.TinyLFU),
gocachex.WithMaxEntries[string, int](10_000),
)cache := gocachex.New[string, int](
gocachex.WithTTL[string, int](5 * time.Minute), // Default TTL
gocachex.WithShards[string, int](128), // Shard count
gocachex.WithPolicy[string, int](policy.ARC), // Eviction policy
gocachex.WithMaxEntries[string, int](1_000_000), // Max entries
gocachex.WithMaxMemory[string, int](1 << 30), // 1GB memory limit
gocachex.WithCleanupInterval[string, int](30 * time.Second), // Cleanup interval
gocachex.WithCleanupDisabled[string, int](), // Disable auto-cleanup
gocachex.WithHasher[string, int](customHasher), // Custom hash function
gocachex.WithClock[string, int](mockClock), // Custom clock (testing)
gocachex.WithLogger[string, int](slog.Default()), // Structured logging
gocachex.WithStatsDisabled[string, int](), // Disable stats overhead
gocachex.WithOnExpired[string, int](expiredHandler), // Expiration callback
gocachex.WithOnEvicted[string, int](evictedHandler), // Eviction callback
gocachex.WithOnSet[string, int](setHandler), // Set callback
gocachex.WithOnDelete[string, int](deleteHandler), // Delete callback
gocachex.WithOnUpdate[string, int](updateHandler), // Update callback
)promExporter := metrics.NewPrometheusExporter("myapp_cache")
http.HandleFunc("/metrics", func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "text/plain; version=0.0.4")
promExporter.WriteTo(w, cache.Stats())
})jsonExporter := metrics.NewJSONExporter(true) // pretty print
jsonExporter.WriteTo(w, cache.Stats())otelExporter := metrics.NewOTelExporter(yourMeterRecorder)
otelExporter.Export(cache.Stats())// File-based with atomic writes.
store := persistence.NewFileStore("cache.dat")
// With gzip compression.
compressedStore := persistence.NewCompressedStore(store)
// Serialize with JSON.
serializer := serialization.NewJSONSerializer()
data, _ := serializer.Marshal(cache.Snapshot())
compressedStore.Save(data)
// Restore.
loaded, _ := compressedStore.Load()
var snapshot map[string]int
serializer.Unmarshal(loaded, &snapshot)ββββββββββββββββββββββββββββββββββββββββββββββββββ
β Cache[K, V] β
β βββββββββββ βββββββββββ βββββββββββ β
β β Shard 0 β β Shard 1 β β Shard N β ... β
β βββββββββββ βββββββββββ βββββββββββ β
β ββRWMutexββ ββRWMutexββ ββRWMutexββ β
β ββββββββββ€β ββββββββββ€β ββββββββββ€β β
β ββ Map ββ ββ Map ββ ββ Map ββ β
β ββββββββββ€β ββββββββββ€β ββββββββββ€β β
β ββPolicy ββ ββPolicy ββ ββPolicy ββ β
β βββββββββββ βββββββββββ βββββββββββ β
β β [pad64] β β [pad64] β β [pad64] β β
β βββββββββββ βββββββββββ βββββββββββ β
β β
β ββββββββββββ ββββββββββββ ββββββββββββ β
β β Stats β β Events β β Cleanup β β
β β (atomic) β β (async) β β (worker) β β
β ββββββββββββ ββββββββββββ ββββββββββββ β
ββββββββββββββββββββββββββββββββββββββββββββββββββ
Key design decisions:
- Power-of-2 sharding with bitwise AND masking (faster than modulo)
- Cache-line padding (64 bytes) between shards to prevent false sharing
- Atomic TTL checks on read (lock-free via
atomic.Int64) - Lazy + proactive expiration (check on Get + background sweep)
- Per-shard policies β no cross-shard coordination needed
- sync.Pool for entry object recycling
# Run all tests with race detector
go test -race -v ./...
# Run benchmarks
go test -bench=. -benchmem -count=3 ./benchmarks/
# Run fuzz tests (60 seconds)
go test -fuzz=FuzzSetGet -fuzztime=60s ./tests/
# Coverage report
go test -coverprofile=coverage.out ./...
go tool cover -func=coverage.outGoCacheX/
βββ cache.go # Main Cache[K,V] public API
βββ config.go # Functional options
βββ entry.go # Cache entry with atomic fields
βββ shard.go # Sharded internals
βββ atomic.go # Atomic ops + GetOrLoad
βββ events.go # Event callbacks
βββ iterator.go # Safe/snapshot/concurrent iterators
βββ hooks.go # Middleware + plugin system
βββ hash.go # Hash functions (maphash + FNV)
βββ clock.go # Clock abstraction (real + mock)
βββ pool.go # sync.Pool integration
βββ errors.go # Sentinel errors
βββ policy/ # 7 eviction policies
β βββ lru.go # Least Recently Used
β βββ lfu.go # Least Frequently Used
β βββ fifo.go # First In First Out
β βββ random.go # Random eviction
β βββ clock.go # Clock (second-chance)
β βββ arc.go # Adaptive Replacement Cache
β βββ tinylfu.go # TinyLFU
β βββ sketch.go # Count-Min Sketch + Bloom filter
βββ stats/ # Lock-free statistics
βββ metrics/ # Prometheus, OTel, JSON exporters
βββ serialization/ # Pluggable serializers (Gob, JSON, MsgPack)
βββ persistence/ # File persistence + compression
βββ internal/ # Cache-line padding, fast hashers
βββ examples/ # Usage examples
βββ tests/ # Unit, fuzz, stress, integration tests
βββ benchmarks/ # Comprehensive benchmarks
- import "github.com/patrickmn/go-cache"
+ import "github.com/gocachex/gocachex"
- c := cache.New(5*time.Minute, 10*time.Minute)
+ c := gocachex.New[string, any](
+ gocachex.WithTTL[string, any](5*time.Minute),
+ gocachex.WithCleanupInterval[string, any](10*time.Minute),
+ )
- c.Set("key", value, cache.DefaultExpiration)
+ c.Set("key", value)
- val, found := c.Get("key")
- myVal := val.(MyType) // type assertion needed!
+ myVal, found := c.Get("key") // type-safe, no assertion!- import "github.com/dgraph-io/ristretto"
+ import "github.com/gocachex/gocachex"
+ import "github.com/gocachex/gocachex/policy"
- cache, _ := ristretto.NewCache(&ristretto.Config{...})
+ cache := gocachex.New[string, MyType](
+ gocachex.WithPolicy[string, MyType](policy.TinyLFU),
+ gocachex.WithMaxEntries[string, MyType](100_000),
+ )Q: Is it safe for concurrent use?
Yes. All operations are thread-safe. Tested with 100,000+ concurrent goroutines and clean under -race.
Q: What's the default eviction policy?
LRU. Change it with WithPolicy().
Q: Can I use integer keys?
Yes. Any comparable type works: string, int, uint64, custom structs, etc.
Q: Does it support generics?
Yes. Full generics throughout. Cache[string, User], Cache[int, []byte], etc.
Q: How many shards should I use?
The default (GOMAXPROCS * 16) works well for most workloads. Increase for extreme write contention, decrease for memory-constrained environments.
Q: Are external dependencies required? No. The core library has zero external dependencies. Prometheus/OTel metrics use lightweight interfaces β no heavy SDK imports.
MIT License β see LICENSE for details.
Built with β€οΈ for the Go community