cache

package
v0.1.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 11, 2026 License: MIT Imports: 4 Imported by: 0

README

cache

import "github.com/brpaz/lib-go/cache"

Package cache provides a key-value Cache abstraction with per-entry expiration, plus implementations for common scenarios.

Storing and retrieving values

Cache stores raw bytes under a string key. Callers are responsible for encoding and decoding their own values:

data, _ := json.Marshal(profile)
_ = c.Set(ctx, "profile:"+userID, data, time.Hour)

raw, err := c.Get(ctx, "profile:"+userID)
if errors.Is(err, cache.ErrNotFound) {
    // load from the source of truth and repopulate the cache
}
Expiration

Set takes a ttl. A ttl <= 0 means the entry never expires:

_ = c.Set(ctx, "session:"+token, data, 30*time.Minute) // expires
_ = c.Set(ctx, "config:flags", data, 0)                // never expires
Testing

Pass Noop when a component needs a Cache but the test doesn't care about caching — every Get misses and every Set/Delete is discarded:

svc := NewProfileService(cache.Noop{})

Use InMemory when a test needs to assert on hits, misses or values without a real backend:

c := cache.NewInMemory()

_ = c.Set(ctx, "key", []byte("value"), time.Minute)
got, err := c.Get(ctx, "key")
require.NoError(t, err)
assert.Equal(t, []byte("value"), got)
Swapping the implementation

Code should depend on the Cache interface rather than a concrete type. This allows swapping InMemory for a distributed backend (e.g. Redis, Memcached) at the wiring layer without touching the rest of the codebase.

Index

Variables

ErrNotFound is returned by Get when key does not exist or has expired.

var ErrNotFound = errors.New("cache: key not found")

type Cache

Cache is a key-value store with per-entry expiration.

Implementations can be in-process (like InMemory) or backed by an external store (e.g. Redis, Memcached) by providing a different implementation at the wiring layer. Values are stored as raw bytes — callers are responsible for encoding and decoding them.

type Cache interface {
    // Get returns the value stored under key, or ErrNotFound if it does not
    // exist or has expired.
    Get(ctx context.Context, key string) ([]byte, error)

    // Set stores value under key, replacing any existing entry. A ttl <= 0
    // means the entry never expires.
    Set(ctx context.Context, key string, value []byte, ttl time.Duration) error

    // Delete removes key. It returns nil whether or not key existed.
    Delete(ctx context.Context, key string) error
}

type InMemory

InMemory is an in-process Cache backed by a map. Entries expire lazily — an expired entry is treated as missing and removed the next time it is read, and is replaced outright on the next write to the same key. Safe for concurrent use.

type InMemory struct {
    // contains filtered or unexported fields
}

func NewInMemory
func NewInMemory() *InMemory

NewInMemory returns a ready-to-use InMemory cache.

func (*InMemory) Delete
func (c *InMemory) Delete(_ context.Context, key string) error

Delete implements Cache.

func (*InMemory) Get
func (c *InMemory) Get(_ context.Context, key string) ([]byte, error)

Get implements Cache.

func (*InMemory) Set
func (c *InMemory) Set(_ context.Context, key string, value []byte, ttl time.Duration) error

Set implements Cache.

type Noop

Noop is a Cache that stores nothing. Get always returns ErrNotFound and Set/Delete are no-ops. Use it as a default when caching is disabled or irrelevant to the code under test.

type Noop struct{}

func NewNoop
func NewNoop() Noop

NewNoop returns a ready-to-use Noop cache.

func (Noop) Delete
func (Noop) Delete(_ context.Context, _ string) error

Delete does nothing and returns nil.

func (Noop) Get
func (Noop) Get(_ context.Context, _ string) ([]byte, error)

Get always returns ErrNotFound.

func (Noop) Set
func (Noop) Set(_ context.Context, _ string, _ []byte, _ time.Duration) error

Set does nothing and returns nil.

Generated by gomarkdoc

Documentation

Overview

Package cache provides a key-value Cache abstraction with per-entry expiration, plus implementations for common scenarios.

Storing and retrieving values

Cache stores raw bytes under a string key. Callers are responsible for encoding and decoding their own values:

data, _ := json.Marshal(profile)
_ = c.Set(ctx, "profile:"+userID, data, time.Hour)

raw, err := c.Get(ctx, "profile:"+userID)
if errors.Is(err, cache.ErrNotFound) {
    // load from the source of truth and repopulate the cache
}

Expiration

Set takes a ttl. A ttl <= 0 means the entry never expires:

_ = c.Set(ctx, "session:"+token, data, 30*time.Minute) // expires
_ = c.Set(ctx, "config:flags", data, 0)                // never expires

Testing

Pass Noop when a component needs a Cache but the test doesn't care about caching — every Get misses and every Set/Delete is discarded:

svc := NewProfileService(cache.Noop{})

Use InMemory when a test needs to assert on hits, misses or values without a real backend:

c := cache.NewInMemory()

_ = c.Set(ctx, "key", []byte("value"), time.Minute)
got, err := c.Get(ctx, "key")
require.NoError(t, err)
assert.Equal(t, []byte("value"), got)

Swapping the implementation

Code should depend on the Cache interface rather than a concrete type. This allows swapping InMemory for a distributed backend (e.g. Redis, Memcached) at the wiring layer without touching the rest of the codebase.

Index

Constants

This section is empty.

Variables

View Source
var ErrNotFound = errors.New("cache: key not found")

ErrNotFound is returned by Get when key does not exist or has expired.

Functions

This section is empty.

Types

type Cache

type Cache interface {
	// Get returns the value stored under key, or ErrNotFound if it does not
	// exist or has expired.
	Get(ctx context.Context, key string) ([]byte, error)

	// Set stores value under key, replacing any existing entry. A ttl <= 0
	// means the entry never expires.
	Set(ctx context.Context, key string, value []byte, ttl time.Duration) error

	// Delete removes key. It returns nil whether or not key existed.
	Delete(ctx context.Context, key string) error
}

Cache is a key-value store with per-entry expiration.

Implementations can be in-process (like InMemory) or backed by an external store (e.g. Redis, Memcached) by providing a different implementation at the wiring layer. Values are stored as raw bytes — callers are responsible for encoding and decoding them.

type InMemory

type InMemory struct {
	// contains filtered or unexported fields
}

InMemory is an in-process Cache backed by a map. Entries expire lazily — an expired entry is treated as missing and removed the next time it is read, and is replaced outright on the next write to the same key. Safe for concurrent use.

func NewInMemory

func NewInMemory() *InMemory

NewInMemory returns a ready-to-use InMemory cache.

func (*InMemory) Delete

func (c *InMemory) Delete(_ context.Context, key string) error

Delete implements Cache.

func (*InMemory) Get

func (c *InMemory) Get(_ context.Context, key string) ([]byte, error)

Get implements Cache.

func (*InMemory) Set

func (c *InMemory) Set(_ context.Context, key string, value []byte, ttl time.Duration) error

Set implements Cache.

type Noop

type Noop struct{}

Noop is a Cache that stores nothing. Get always returns ErrNotFound and Set/Delete are no-ops. Use it as a default when caching is disabled or irrelevant to the code under test.

func NewNoop

func NewNoop() Noop

NewNoop returns a ready-to-use Noop cache.

func (Noop) Delete

func (Noop) Delete(_ context.Context, _ string) error

Delete does nothing and returns nil.

func (Noop) Get

func (Noop) Get(_ context.Context, _ string) ([]byte, error)

Get always returns ErrNotFound.

func (Noop) Set

func (Noop) Set(_ context.Context, _ string, _ []byte, _ time.Duration) error

Set does nothing and returns nil.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL