Skip to content

maslyukov0/single_value_cache

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Single Value Cache

This is a tiny, focused Go library designed for those moments when you need to cache just one thing the best way, that cache libraries do not provide.

Whether it's a configuration object, a token, or a result from a heavy database query, this library helps you handle it without the boilerplate of a full-blown key-value store.

Why use this?

Caching can be tricky. You often have to deal with:

  • Race conditions: Multiple goroutines trying to update the same value.
  • Thundering herds: A sudden spike in requests when the cache expires, all hitting your database at once.
  • Type safety: Casting any back and forth.

This library solves these problems by combining Generics, TTL (Time-To-Live), and Singleflight protection in a simple, human-friendly package.

Features

  • Type Safe: Built with Go Generics, so no more type assertions.
  • Smart Loading: Using golang.org/x/sync/singleflight, it ensures that even if 100 goroutines request an expired value, your loader function is only called once.
  • Automatic Expiration: Set a TTL and let the cache handle the rest.
  • Modern Go: Written with Go 1.26 idioms in mind.

Installation

go get github.com/maslyukov0/single-cache

Quick Start

It's designed to be intuitive. Here’s how you can use it:

package main

import (
	"context"
	"fmt"
	"time"
	"github.com/maslyukov0/single_value_cache"
)

func main() {
	// 1. Define how to load your data
	loader := func(ctx context.Context) (string, error) {
		fmt.Println("--- Loading data from source... ---")
		time.Sleep(100 * time.Millisecond) // Simulate some work
		return "Hello, World!", nil
	}

	// 2. Create a cache with a 5-minute TTL
	c := cache.NewSingleValueCache(5*time.Minute, loader)

	// 3. Get your value! 
	// The first call loads it, subsequent calls (within TTL) return the cached value.
	val, _ := c.Get(context.Background())
	fmt.Println("Result:", val)
}

Behind the Scenes

When you call Get():

  1. It checks if the value is still fresh.
  2. If it's expired (or not yet loaded), it uses a "singleflight" lock to ensure only one loader runs at a time.
  3. Other concurrent callers wait for that single loader to finish and then share the result.

Development

We take reliability seriously. The project comes with a comprehensive test suite and is automatically tested via GitHub Actions.

go test -v ./...

Made with ❤️ for the Go community.

About

Blazingly fast library that allows safe singleton caches. Built with generics and type safety

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages