Context key type: Final recommendation

June 27, 2025

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! Ouch!

But this also helps to serve as an example in my final recommendation.


After going through a number of types we could use for our context keys, two strong contenders stand out:

Up to now, I’ve always used the struct approach. I picked up this habit while reading some code in the standard library, and never really evaluated alternatives until writing this series.

Now that I’ve taken the time to consider alternatives, I expect I’ll be using unexported string types from now on. And that is ultimately my final recommendation, with one small caveat:

As I’ve demonstrated above, it’s very easy to accidentally forget to declare constants with the appropriate type. If this concerns, you, using a struct is more explicit, and harder to do incorrectly.

const KeyBlue = "blue" // oops

const KeyRed contextKey = "red" // Good!

var KeyGreen = &contextKey{"green"} // Hard to do incorrectly

However, since these defintions are necissarily constrained to a single package (and likely a single file), it’s hopefully pretty easy to ensure that your constant defintions are of the correct type, and avoid this problem.


Share this

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

Unsure? Browse the archive .

Related Content


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.


String context keys

By now we’ve looked at empty structs (struct{}), and integers as possible context key types. Today, let’s consider string context keys. type contextKey string const ( KeyUserID contextKey = "user_id" KeyTransactionID contextKey = "transaction_id" KeyMessageID contextKey = "message_id" ) How does this stack up against our 5 criteria? Must be comparable. ✅ Check. Use minimal memory. ✅ Using a string will typically use a bit more memory than an integer (typically 32 bytes vs 16), but still quite minimal.


Integer context keys

We’re looking at different types for context keys. So far, we’ve looked at empty structs (struct{}), and found it to be less than ideal. Today, let’s consider integer context keys. This seems handy, right? type contextKey int const ( KeyUserID int = iota KeyTransactionID KeyMessageID . . . KeyFoo ) Let’s see how it stacks up to our 5 criteria: Must be comparable. ✅ No problem! Use minimal membory. ✅ int doesn’t have as small a memory footprint as struct{}’s zero bytes, but it’s still pretty small.

Get daily content like this in your inbox!

Subscribe