context.WithValue

July 11, 2025

func WithValue

func WithValue(parent Context, key, val any) Context

WithValue returns a derived context that points to the parent Context. In the derived context, the value associated with key is val.

Use context Values only for request-scoped data that transits processes and APIs, not for passing optional parameters to functions.

The provided key must be comparable and should not be of type string or any other built-in type to avoid collisions between packages using context. Users of WithValue should define their own types for keys. To avoid allocating when assigning to an interface{}, context keys often have concrete type struct{}. Alternatively, exported context key variables’ static type should be a pointer or interface.

We’ve already talked pretty extensively about when to use, and not use, context.WithValue, and how to select context keys. So we won’t repeat that here. Instead, we’ll look at the example provided in the docs, and disect it a bit.

Example

This example demonstrates how a value can be passed to the context and also how to retrieve it if it exists.

import (
	"context"
	"fmt"
)

func main() {
	type favContextKey string

	f := func(ctx context.Context, k favContextKey) {
		if v := ctx.Value(k); v != nil {
			fmt.Println("found value:", v)
			return
		}
		fmt.Println("key not found:", k)
	}

	k := favContextKey("language")
	ctx := context.WithValue(context.Background(), k, "Go")

	f(ctx, k)
	f(ctx, favContextKey("color"))
}

This short example shows a good example of a custom context key type, based on string, as we’ve previously discussed.

Then it shows a utility function, f, that simply prints the value associated with a context key, or a message that the key was not found.

Then it calls context.WithValue to create a new context with a value associated with the key favContextKey("language"). Then finally it calls f twice, once with a key that exists, and once with a key that does not.

I think the main atypical thing to point out here is that it’s rare that you’ll retrieve a value from a context, and not use a type assertion to convert it to an expected type. Because this example simply prints the value, it doesn’t need to do that. But in practice, you’ll almost always want to do something like this:

if v, ok := ctx.Value(k).(string); ok {
	fmt.Println("found value:", v)
	return
}

Share this

Direct to your inbox, daily. I respect your privacy .

Unsure? Browse the archive .

Related Content


Context key/value utilities

So we’ve finally settled on a suitable type for our context key types: string, or maybe a non-empty struct. We also understand that to guard against key collisions, we need our custom type to be un-exported. type contextKey string const KeyUserID = contextKey("user_id") Now code anywhere in your project can use the context key without fear of collision. Done! Right? I’m sure you know the fact that I’m asking means there’s more we can do.


Context key type: Final recommendation

First, a correction! An astute reader pointed out that I made a small mistake in my post on June, 10, with regard to string context keys. My code example showed: type contextKey string const ( KeyUserID = "user_id" KeyTransactionID = "transaction_id" KeyMessageID = "message_id" ) But it should have been: type contextKey string const ( KeyUserID contextKey = "user_id" KeyTransactionID contextKey = "transaction_id" KeyMessageID contextKey = "message_id" ) This is a nasty kind of bug, because the code will continue to work as expected—just without any protection from key collisions!


Struct context keys

First off, an apology for being rather unreliable with my “daily” emails. I’m in the middle of some traveling (was in the UK and Netherlands last week, and will be on a US road trip starting tomorrow), so I’m writing when I have a spare moment, which isn’t that often. I’ve been talking about finding the ideal type for a context key. So far I’ve looked at empty structs (e.g. struct{}), integers, and strings.

Get daily content like this in your inbox!

Subscribe