Documentation
¶
Overview ¶
Package ctxval provides typed helpers for storing and retrieving request-scoped values in context.Context.
Values are keyed by their Go type. Each type can have at most one value in a context. Use named types to distinguish values of the same underlying type. Type aliases (=) share the same key as the aliased type:
type RequestID string
type TraceID string
ctx = ctxval.With(ctx, RequestID("abc"))
ctx = ctxval.With(ctx, TraceID("xyz"))
reqID := ctxval.Get[RequestID](ctx) // Option[RequestID]("abc")
trID := ctxval.Get[TraceID](ctx) // Option[TraceID]("xyz")
For code that only needs one value per type (e.g., middleware injecting a User into context), the package-level With and Get functions are convenient. For shared or public boundaries where multiple values of the same type coexist, prefer Key — it gives each value a unique identity without requiring a new named type:
var userKey = ctxval.NewKey[User]() ctx = userKey.With(ctx, currentUser) userOpt := userKey.From(ctx) // Option[User]
This package is for request-scoped data that crosses API boundaries (user IDs, trace IDs, auth tokens). It is not for optional parameters, dependency injection, or service locators.
Index ¶
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func Get ¶ added in v0.56.0
Get retrieves the value of type T from ctx, returning a not-ok option if no value of that type is present. T must match the exact static type used in With; interface and concrete types are distinct keys.
Panics if ctx is nil (same as context.Context.Value).
Example ¶
package main
import (
"context"
"fmt"
"github.com/binaryphile/fluentfp/ctxval"
)
// ExRequestID is a distinct type for request IDs in context.
type ExRequestID string
func main() {
// Get returns not-ok when the type isn't in the context.
ctx := context.Background()
id := ctxval.Get[ExRequestID](ctx)
fmt.Println(id.IsOk())
fmt.Println(id.Or("fallback"))
}
Output: false fallback
func With ¶
With returns a child context carrying val, keyed by its type T. A subsequent call with the same T shadows the parent's value.
For distinct semantic keys of the same type, use NewKey instead.
Panics if ctx is nil (same as context.WithValue).
Example ¶
package main
import (
"context"
"fmt"
"github.com/binaryphile/fluentfp/ctxval"
)
// ExRequestID is a distinct type for request IDs in context.
type ExRequestID string
func main() {
// Store a request ID in context, keyed by type.
ctx := ctxval.With(context.Background(), ExRequestID("req-abc-123"))
id := ctxval.Get[ExRequestID](ctx).Or("unknown")
fmt.Println(id)
}
Output: req-abc-123
Types ¶
type Key ¶
type Key[T any] struct { // contains filtered or unexported fields }
Key is a named context key for values of type T. Unlike With/Get, which key by type alone, each Key is a unique identity — multiple keys can carry the same type T without collision.
Typically create with NewKey. Declare as package-level variables.
func NewKey ¶
NewKey returns a new unique key for values of type T. Each call returns a distinct key (pointer identity).
Example ¶
package main
import (
"context"
"fmt"
"github.com/binaryphile/fluentfp/ctxval"
)
func main() {
// Two keys of the same type don't collide.
adminKey := ctxval.NewKey[string]()
userKey := ctxval.NewKey[string]()
ctx := context.Background()
ctx = adminKey.With(ctx, "root")
ctx = userKey.With(ctx, "alice")
fmt.Println(adminKey.From(ctx).Or(""))
fmt.Println(userKey.From(ctx).Or(""))
}
Output: root alice