On Thu, Jan 7, 2021 at 10:20 AM Axel Wagner
<
axel.wa...@googlemail.com> wrote:
>
> Hi,
>
> this works fine, but it incurs an extra allocation (AFAIK both for storing the data, and for looking it up). requestContext is not zero-sized, so to store it in an interface{}, a new value must be allocated and put into the interface. This also has to happen on lookup (I don't think the compiler optimizes that, today), because you need to convert it to interface{} when passing it to `Value`. The recommended way
>
> type ctxKey struct{}
>
> type requestContext struct {
> requestID string
> requestID
> }
>
> ctx := context.WithValue(req.Context(), ctxKey{}, requestContext{"request-123-abc", "client-451"})
>
> does not have this drawback - zero-sized values are special, because there can only be one of them, so the compiler is free to re-use the same address. So, a conversion of a zero-sized value to ctxKey{} is free.
> I would also argue, that the code is clearer and safer that way - because there can only be one value of type ctxKey{}, you don't have to wonder what would happen if you use different keys of the same type - and fmt.Println only prints the type-name of keys, not the actual value (
https://play.golang.org/p/pAj6RclqAGw), so if you encounter a bug with unexpected context-contents, it's just one less thing to worry about.
>
> So, yes, your way absolutely works. I would still strongly recommend going the "official" route. It's one line of additional overhead, but there are concrete technical benefits (as well as just the general benefits of uniformity).