Gocache
☔️ A complete Go cache library that brings you multiple ways of managing your caches
Install / Use
/learn @eko/GocacheREADME
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
- Memory (bigcache) (allegro/bigcache)
- Memory (ristretto) (dgraph-io/ristretto)
- Memory (go-cache) (patrickmn/go-cache)
- Memcache (bradfitz/memcache)
- Redis (go-redis/redis)
- Redis (rueidis) (redis/rueidis)
- Freecache (coocood/freecache)
- Pegasus (apache/incubator-pegasus) benchmark
- Hazelcast (hazelcast-go-client/hazelcast)
- More to come soon
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
node-connect
339.5kDiagnose OpenClaw node connection and pairing failures for Android, iOS, and macOS companion apps
xurl
339.5kA CLI tool for making authenticated requests to the X (Twitter) API. Use this skill when you need to post tweets, reply, quote, search, read posts, manage followers, send DMs, upload media, or interact with any X API v2 endpoint.
frontend-design
83.9kCreate distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, or applications. Generates creative, polished code that avoids generic AI aesthetics.
openai-whisper-api
339.5kTranscribe audio via OpenAI Audio Transcriptions API (Whisper).

