SkillAgentSearch skills...

Gocache

☔️ A complete Go cache library that brings you multiple ways of managing your caches

Install / Use

/learn @eko/Gocache
About this skill

Quality Score

0/100

Supported Platforms

Universal

README

Test GoDoc GoReportCard codecov

Gocache

Guess what is Gocache? a Go cache library. This is an extendable cache library that brings you a lot of features for caching data.

Overview

Here is what it brings in detail:

  • ✅ Multiple cache stores: actually in memory, redis, or your own custom store
  • ✅ A chain cache: use multiple cache with a priority order (memory then fallback to a redis shared cache for instance)
  • ✅ A loadable cache: allow you to call a callback function to put your data back in cache
  • ✅ A metric cache to let you store metrics about your caches usage (hits, miss, set success, set error, ...)
  • ✅ A marshaler to automatically marshal/unmarshal your cache values as a struct
  • ✅ Define default values in stores and override them when setting data
  • ✅ Cache invalidation by expiration time and/or using tags
  • ✅ Use of Generics

Built-in stores

Built-in metrics providers

Installation

To begin working with the latest version of gocache, you can import the library in your project:

go get github.com/eko/gocache/lib/v4

and then, import the store(s) you want to use between all available ones:

go get github.com/eko/gocache/store/bigcache/v4
go get github.com/eko/gocache/store/freecache/v4
go get github.com/eko/gocache/store/go_cache/v4
go get github.com/eko/gocache/store/hazelcast/v4
go get github.com/eko/gocache/store/memcache/v4
go get github.com/eko/gocache/store/pegasus/v4
go get github.com/eko/gocache/store/redis/v4
go get github.com/eko/gocache/store/rediscluster/v4
go get github.com/eko/gocache/store/rueidis/v4
go get github.com/eko/gocache/store/ristretto/v4

Then, simply use the following import statements:

import (
	"github.com/eko/gocache/lib/v4/cache"
	"github.com/eko/gocache/store/redis/v4"
)

If you run into any errors, please be sure to run go mod tidy to clean your go.mod file.

Available cache features in detail

A simple cache

Here is a simple cache instantiation with Redis but you can also look at other available stores:

Memcache

memcacheStore := memcache_store.NewMemcache(
	memcache.New("10.0.0.1:11211", "10.0.0.2:11211", "10.0.0.3:11212"),
	store.WithExpiration(10*time.Second),
)

cacheManager := cache.New[[]byte](memcacheStore)
err := cacheManager.Set(ctx, "my-key", []byte("my-value"),
	store.WithExpiration(15*time.Second), // Override default value of 10 seconds defined in the store
)
if err != nil {
    panic(err)
}

value := cacheManager.Get(ctx, "my-key")

cacheManager.Delete(ctx, "my-key")

cacheManager.Clear(ctx) // Clears the entire cache, in case you want to flush all cache

Memory (using Bigcache)

bigcacheClient, _ := bigcache.NewBigCache(bigcache.DefaultConfig(5 * time.Minute))
bigcacheStore := bigcache_store.NewBigcache(bigcacheClient)

cacheManager := cache.New[[]byte](bigcacheStore)
err := cacheManager.Set(ctx, "my-key", []byte("my-value"))
if err != nil {
    panic(err)
}

value := cacheManager.Get(ctx, "my-key")

Memory (using Ristretto)

import (
	"github.com/dgraph-io/ristretto"
	"github.com/eko/gocache/lib/v4/cache"
	"github.com/eko/gocache/lib/v4/store"
	ristretto_store "github.com/eko/gocache/store/ristretto/v4"
)
ristrettoCache, err := ristretto.NewCache(&ristretto.Config[string, string]{
	NumCounters: 1000,
	MaxCost: 100,
	BufferItems: 64,
})
if err != nil {
    panic(err)
}
ristrettoStore := ristretto_store.NewRistretto(ristrettoCache)

cacheManager := cache.New[string](ristrettoStore)
err := cacheManager.Set(ctx, "my-key", "my-value", store.WithCost(2))
if err != nil {
    panic(err)
}

value := cacheManager.Get(ctx, "my-key")

cacheManager.Delete(ctx, "my-key")

Memory (using Go-cache)

gocacheClient := gocache.New(5*time.Minute, 10*time.Minute)
gocacheStore := gocache_store.NewGoCache(gocacheClient)

cacheManager := cache.New[[]byte](gocacheStore)
err := cacheManager.Set(ctx, "my-key", []byte("my-value"))
if err != nil {
	panic(err)
}

value, err := cacheManager.Get(ctx, "my-key")
if err != nil {
	panic(err)
}
fmt.Printf("%s", value)

Redis

redisStore := redis_store.NewRedis(redis.NewClient(&redis.Options{
	Addr: "127.0.0.1:6379",
}))

cacheManager := cache.New[string](redisStore)
err := cacheManager.Set(ctx, "my-key", "my-value", store.WithExpiration(15*time.Second))
if err != nil {
    panic(err)
}

value, err := cacheManager.Get(ctx, "my-key")
switch err {
	case nil:
		fmt.Printf("Get the key '%s' from the redis cache. Result: %s", "my-key", value)
	case redis.Nil:
		fmt.Printf("Failed to find the key '%s' from the redis cache.", "my-key")
	default:
	    fmt.Printf("Failed to get the value from the redis cache with key '%s': %v", "my-key", err)
}

Redis Client-Side Caching (using rueidis)

client, err := rueidis.NewClient(rueidis.ClientOption{InitAddress: []string{"127.0.0.1:6379"}})
if err != nil {
    panic(err)
}

cacheManager := cache.New[string](rueidis_store.NewRueidis(
    client,
    store.WithExpiration(15*time.Second),
    store.WithClientSideCaching(15*time.Second)),
)

if err = cacheManager.Set(ctx, "my-key", "my-value"); err != nil {
    panic(err)
}

value, err := cacheManager.Get(ctx, "my-key")
if err != nil {
    log.Fatalf("Failed to get the value from the redis cache with key '%s': %v", "my-key", err)
}
log.Printf("Get the key '%s' from the redis cache. Result: %s", "my-key", value)

Freecache

freecacheStore := freecache_store.NewFreecache(freecache.NewCache(1000), store.WithExpiration(10 * time.Second))

cacheManager := cache.New[[]byte](freecacheStore)
err := cacheManager.Set(ctx, "by-key", []byte("my-value"), opts)
if err != nil {
    panic(err)
}

value := cacheManager.Get(ctx, "my-key")

Pegasus

pegasusStore, err := pegasus_store.NewPegasus(&store.OptionsPegasus{
    MetaServers: []string{"127.0.0.1:34601", "127.0.0.1:34602", "127.0.0.1:34603"},
})

if err != nil {
    fmt.Println(err)
    return
}

cacheManager := cache.New[string](pegasusStore)
err = cacheManager.Set(ctx, "my-key", "my-value", store.WithExpiration(10 * time.Second))
if err != nil {
    panic(err)
}

value, _ := cacheManager.Get(ctx, "my-key")

Hazelcast

hzClient, err := hazelcast.StartNewClient(ctx)
if err != nil {
    log.Fatalf("Failed to start client: %v", err)
}

hzMap, err := hzClient.GetMap(ctx, "gocache")
if err != nil {
    b.Fatalf("Failed to get map: %v", err)
}

hazelcastStore := hazelcast_store.NewHazelcast(hzMap)

cacheManager := cache.New[string](hazelcastStore)
err := cacheManager.Set(ctx, "my-key", "my-value", store.WithExpiration(15*time.Second))
if err != nil {
    panic(err)
}

value, err := cacheManager.Get(ctx, "my-key")
if err != nil {
    panic(err)
}
fmt.Printf("Get the key '%s' from the hazelcast cache. Result: %s", "my-key", value)

A chained cache

Here, we will chain caches in the following order: first in memory with Ristretto store, then in Redis (as a fallback):

// Initialize Ristretto cache and Redis client
ristrettoCache, err := ristretto.NewCache(&ristretto.Config[string, string]{
    NumCounters: 1000,
    MaxCost: 100,
    BufferItems: 64,
})
if err != nil {
    panic(err)
}

redisClient := redis.NewClient(&redis.Options{Addr: "127.0.0.1:6379"})

// Initialize stores
ristrettoStore := ristretto_store.NewRistretto(ristrettoCache)
redisStore := redis_store.NewRedis(redisClient, store.WithExpiration(5*time.Second))

// Initialize chained cache
cacheManager := cache.NewChain[any](
    cache.New[any](ristrettoStore),
    cache.New[any](redisStore),
)

// ... Then, do what you want with your cache

Chain cache also put data back in previous caches when it's found so in this case, if ristretto doesn't have the data in its cache but redis have, data will also get setted back into ristretto (memory) cache.

A loadable cache

This cache will provide a load function that acts as a callable function and will set your data back in your cache in case they are not available:

type Book struct {
	ID string
	Name string
}

// Initialize Redis client and store
redisClient := redis.NewClient(&redis.Options{Addr: "127.0.0.1:6379"})
redisStore := redis_store.NewRedis(redisClient)

// Initialize a load function that loads your data from a custom source
loadFunction := func(ctx context.Context, key any) (*Book, error) {
    // ... retrieve value from available source
    return &Book{ID: 1, Name: "My test amazing book"}, nil
}

// Initialize loadable cache
cacheManager := cache.NewLoadable[*Book](
	loadFunction,
	cache.New[*Book](redisStore),
)

// 

Related Skills

View on GitHub
GitHub Stars2.8k
CategoryDevelopment
Updated1d ago
Forks220

Languages

Go

Security Score

100/100

Audited on Mar 27, 2026

No findings