Skip to content

Instantly share code, notes, and snippets.

@goodevilgenius
Created October 10, 2025 17:07
Show Gist options
  • Save goodevilgenius/91b2291ead3008137b2531532f80d851 to your computer and use it in GitHub Desktop.
Save goodevilgenius/91b2291ead3008137b2531532f80d851 to your computer and use it in GitHub Desktop.
Strongly typed values from context with generics #go #golang #context #generics
package ctx
import "context"
// Value returns a strongly-typed value from the given context using ctx.Value.
// ok will be true if found in the context and if the correct type.
func Value[T any](ctx context.Context, key any) (val T, ok bool) {
if val, ok = ctx.Value(key).(T); ok {
return val, ok
}
var zero T
return zero, false
}
// AssignValue will set the value of ptr to the value from Value(ctx, key), if it's
// found in the context and the same type as ptr.
func AssignValue[T any](ctx context.Context, key any, ptr *T) bool {
val, ok := Value[T](ctx, key)
if ok {
*ptr = val
}
return ok
}
@goodevilgenius
Copy link
Author

This could be used like this:

import (
	ctxUtils "ctx"
	"context"
	"net/http"
)

type User struct {
    UserID uint
    Email string
    Name string
}

func AuthMiddleware(next http.Handler) http.Handler {
    return http.HandlerFunc(func (wr http.ResponseWriter, req *http.Request) {
        // Do something to get and verify a user from the request
        ctx := context.WithValue(req.Context(), "user", user)
        req = req.WithContext(ctx)
        next.ServeHttp(wr, req)
    })
}

func Hello(wr http.ResponseWriter, req *http.Request) {
    user, ok := ctxUtils.Value[User](req.Context(), "user")
    if !ok {
        user.Name = "World"
    }
    w.Write([]byte("Hello, " + user.Name))
}

func main() {
	mux := http.NewServeMux()

	mux.Handle("GET /", Hello)

	log.Print("listening on :3000...")
	err := http.ListenAndServe(":3000", mux)
	log.Fatal(err)
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment