How to copy Context object without deriving
Asked Answered
O

2

22

I want to make a copy of a context object - a request context to be exact, and make use of it later on in a separate go routine.

Problem is if I derive the request context using context.WithCancel(reqCtx) once the HTTP handler for this request is finished, not only will the original request context be cancelled, but also the copy of the request context will also be canceled.

I'd like to be able to copy the original request context and not have it canceled by the original context after the HTTP handler has finished executing.

Ohmmeter answered 15/12, 2019 at 22:42 Comment(5)
why not create a new context then? And just copy values or whatever you need over yourself. You can get a new context with context.Background()Daradarach
How can I know which values to fetch from the context? The values will vary depending on the scenarios. I'm looking for something that won't make me manually copy values from one context to another.Ohmmeter
Maybe you can give the scenarios? It seems to me you try to pass around too much data in contexts rather then just constructing structs and pass them around. Maybe this also helps #40380460Daradarach
What happens if request's context reaches its deadline and your context will not ? You should not create new context, use requests context copy and store your values thereSurfeit
To answer why anyone would reasonably want to do this, imagine that for some request, you don't want anything the handler does to be interruptible by the client hanging up, BUT you've also got request-specific data, like user ID maybe, that's been poked into the context by an authentication filter. You don't want to lose the user ID and you also don't want to pass a child of your request context to the uninterruptible operations. You could copy the ID from one context to another, but this means your handlers need to know a whole lot about what the filters have done to the context.Mclaughlin
E
13

Here's how to make a context that uses values from some other context, but not cancelation:

type valueOnlyContext struct{ context.Context }
func (valueOnlyContext) Deadline() (deadline time.Time, ok bool) { return }
func (valueOnlyContext) Done() <-chan struct{} { return nil }
func (valueOnlyContext) Err() error { return nil }

Use it like this:

 ctx := valueOnlyContext{reqCtx}

Using the values without cancelation is probably outside the design intent of the context package. If the designers of the package thought this is a good thing, I would have expected them to bundle up the above in a context package function.

Endoergic answered 15/12, 2019 at 22:42 Comment(0)
E
2

context.WithoutCancel was added in version 1.21.0

Elbring answered 15/1 at 12:21 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.