Cache & logging
Cache
The cache package
is a generic, thread-safe, in-memory cache where every entry expires after the
same duration. A background goroutine purges expired entries; call Stop when
you are done.
c, err := cache.New[string](time.Minute)
if err != nil {
return err
}
defer c.Stop()
c.Set("greeting", "hello")
if v, ok := c.Lookup("greeting"); ok {
fmt.Println(v)
}
WriteThruLookup computes a missing value and caches it, coalescing concurrent
callers so the (possibly expensive) lookup runs at most once:
v, err := c.WriteThruLookup("user:42", func() (User, error) {
return loadUser(ctx, 42)
})
It backs the secret-manager cacher (see Secrets & keys).
Logging
The logging
package is a thin layer over the standard library’s log/slog. A logger is
carried on the context; retrieve it with FromContext, which returns a sensible
default when none is set, so callers never have to nil-check.
logger := logging.NewLogger(slog.LevelInfo, devMode) // JSON in prod, text in dev
ctx = logging.WithLogger(ctx, logger)
// Deeper in the stack:
logging.FromContext(ctx).Info("handled request", "path", "/")
// Components identify themselves:
logging.Named(logger, "middleware.CSRF").Debug("validated token")
The PopulateLogger middleware installs a request-scoped logger tagged with the
request and trace IDs, so every line within a request is correlated.