Skip to content

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

License

Notifications You must be signed in to change notification settings

pzentenoe/go-cache

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

29 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

go-cache

codecov CI Go Report Card License GitHub release

FOSSA Status FOSSA Status

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)

Recent Updates

The latest release adds overflow protection, janitor control, and complete ShardedCache API parity. See CHANGELOG.md for full version history and release notes.

Performance

Standard Cache

  • Suitable for most applications
  • Single lock for all operations
  • ~500,000 ops/sec with 100 concurrent goroutines

Sharded Cache

  • Recommended for high-concurrency scenarios
  • Multiple independent caches with separate locks
  • ~2,000,000 ops/sec with 100 concurrent goroutines (4x improvement)
  • Configurable shard count (8, 16, 32, 64)

When to use sharded cache:

  • βœ… High concurrent read/write operations (100+ goroutines)
  • βœ… Lock contention identified in profiling
  • βœ… Maximum throughput required

See Sharded Cache Guide for benchmarks and 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

License

Stars

Watchers

Forks

Packages

No packages published