Skip to content

Latest commit

Β 

History

46 Commits

Folders and files

NameName
Last commit message
Last commit date
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

go-cache

CI codecov PkgGoDev Go 1.18+ License: MIT

FOSSA License FOSSA Security

High-performance, thread-safe in-memory cache for Go with expiration support and advanced features.

Features

  • ⚑ High Performance: Optimized for concurrent access with optional sharding
  • πŸ”’ Thread-Safe: All operations protected with RWMutex
  • ⏰ Flexible Expiration: Per-item, default, or no expiration
  • 🧹 Janitor: Background cleanup with runtime control
  • πŸ’Ύ Serialization: Persist cache to disk using Gob encoding
  • πŸ›‘οΈ Overflow Protection: Built-in protection for numeric operations
  • πŸ“Š High Concurrency: Sharded cache for reduced lock contention (2-4x faster)
  • 🎯 Simple API: Intuitive interface, easy to integrate

Quick Start

Installation

go get github.com/pzentenoe/go-cache

Basic Example

package main

import (
    "fmt"
    "time"
    "github.com/pzentenoe/go-cache"
)

func main() {
    // Create cache with 5-minute default expiration and 10-minute cleanup
    c := cache.New(5*time.Minute, 10*time.Minute)

    // Set a value
    c.Set("mykey", "myvalue", cache.DefaultExpiration)

    // Get a value
    if val, found := c.Get("mykey"); found {
        fmt.Println("Found:", val)
    }
}

High-Concurrency Example

// Use sharded cache for high-concurrency workloads
sc := cache.NewSharded(5*time.Minute, 10*time.Minute, 32)

// Same API as standard cache
sc.Set("key", "value", cache.DefaultExpiration)
val, found := sc.Get("key")

Documentation

πŸ“š Guides

πŸ’‘ Examples

Runnable examples in examples/:

Run any example:

cd examples/basic && go run main.go

Core Operations

Basic CRUD

// Set operations
c.Set("key", "value", cache.DefaultExpiration)
c.SetDefault("key", "value")
c.Add("key", "value", 5*time.Minute)    // Only if not exists
c.Replace("key", "new", 5*time.Minute)  // Only if exists

// Get operations
val, found := c.Get("key")
val, expTime, found := c.GetWithExpiration("key")

// Delete operations
c.Delete("key")
c.DeleteExpired() // Remove expired items
c.Flush()         // Remove all items

Numeric Operations

All numeric operations include overflow/underflow protection:

// Increment/Decrement
c.Increment("counter", 1)
c.Decrement("counter", 1)
c.IncrementFloat("price", 5.50)

// Type-safe operations with error handling
result, err := c.IncrementUint64("views", 100)
if err != nil {
    // Overflow would occur
}

Persistence

// Save and load cache to/from disk
c.SaveFile("cache.gob")
c.LoadFile("cache.gob")

Janitor Control

// Runtime cleanup management
c.PauseJanitor()
c.ResumeJanitor()
c.SetJanitorInterval(5 * time.Minute)

// Stop janitor goroutine when done
c.Close()

Recent Updates

The latest release (v1.4.0) adds sentinel errors for errors.Is, fixes several panic and race conditions in janitor lifecycle and typed operations, and deduplicates internals with generics β€” with full backward compatibility. See CHANGELOG.md for full version history and release notes.

Performance

Measured on Apple M4 Pro, Go 1.26, go test -bench=. -benchmem -benchtime=1s. All operations are zero-allocation:

Benchmark ns/op B/op allocs/op
Cache Get (not expiring) 7.2 0 0
Cache Get (expiring) 33.7 0 0
Cache Set 13.6 0 0
Cache IncrementInt64 26.3 7 0
ShardedCache Get (not expiring) 10.3 0 0
ShardedCache Set 18.7 0 0
ShardedCache Increment 28.6 8 0

Under concurrent load the sharded cache pulls ahead by design (per-shard locks):

Concurrent benchmark (100 goroutines, own keys) Cache ShardedCache Speedup
Increment 125.6 ns/op 33.5 ns/op ~3.7x
Get (10k goroutines, not expiring) 124.6 ns/op 12.1 ns/op ~10x

When to use which

Standard cache (New):

  • Suitable for most applications
  • Single RWMutex for all operations
  • Fastest single-threaded reads

Sharded cache (NewSharded):

  • Recommended for high-concurrency scenarios
  • Independent shards with separate locks (configurable: 8, 16, 32, 64)
  • βœ… High concurrent read/write operations (100+ goroutines)
  • βœ… Lock contention identified in profiling
  • βœ… Maximum throughput required

Run them yourself:

go test -run=NONE -bench=. -benchmem

See Sharded Cache Guide for best practices.

Thread Safety

All operations are thread-safe and can be called from multiple goroutines:

var wg sync.WaitGroup
for i := 0; i < 100; i++ {
    wg.Add(1)
    go func(id int) {
        defer wg.Done()
        c.Set(fmt.Sprintf("key%d", id), id, cache.DefaultExpiration)
        c.Get(fmt.Sprintf("key%d", id))
    }(i)
}
wg.Wait()

Working with Types

The cache uses interface{} internally, supporting any Go type. Use type assertions when retrieving values:

// Storing values
c.Set("user", User{Name: "Alice"}, cache.DefaultExpiration)
c.Set("count", 42, cache.DefaultExpiration)

// Retrieving with type assertion
if val, found := c.Get("user"); found {
    user := val.(User)  // Type assertion
    fmt.Println(user.Name)
}

// Safe type assertion
if val, found := c.Get("count"); found {
    if count, ok := val.(int); ok {
        fmt.Println("Count:", count)
    }
}

For numeric operations, use the built-in increment/decrement methods which handle types safely.

Contributing

We welcome contributions! Please:

  1. Fork the repository
  2. Create a feature branch (git checkout -b feature/amazing-feature)
  3. Add tests for new functionality
  4. Ensure tests pass and coverage is maintained (currently 92.9%):
    go test -race ./...        # Run with race detector
    go test -cover ./...       # Check coverage
  5. Commit your changes (git commit -m 'Add amazing feature')
  6. Push to the branch (git push origin feature/amazing-feature)
  7. Open a Pull Request

License

This project is licensed under the MIT License - see LICENSE file for details.

Changelog

See CHANGELOG.md for version history and release notes.

Support

Buy Me a Coffee

Buy Me A Coffee

Thank you for your support! ❀️

Author

Pablo Zenteno - pzentenoe

About

About An in-memory key:value store/cache (similar to Memcached) library for Go

Resources

Stars

4 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages