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.