How to Clone a Go Context without Cancel Propagation
In the Go programming language, a context.Context carries metadata and cancellation signals between functions and goroutines. However, it may be desirable to create a copy of a context that retains the same values but does not inherit the cancellation status of the original.
Use Case:
This scenario arises when an HTTP request's context gets canceled after returning the response to the client, but you need to perform an asynchronous task in a separate goroutine that will likely outlive the parent context.
Solution:
1. Create a Custom Context Implementation:
Prior to Go 1.21, one approach was to create your own context.Context implementation that is never canceled:
import ( "context" "time" ) type noCancel struct { ctx context.Context } func (c noCancel) Deadline() (time.Time, bool) { return time.Time{}, false } func (c noCancel) Done() <-chan struct{} { return nil } func (c noCancel) Err() error { return nil } func (c noCancel) Value(key interface{}) interface{} { return c.ctx.Value(key) }
Then, you can create a new context using this implementation:
ctxWithoutCancel := WithoutCancel(ctx)
2. Use WithoutCancel Function (Go 1.21 ):
As of Go 1.21, the context package includes a WithoutCancel function that simplifies this process:
ctxWithoutCancel := context.WithoutCancel(ctx)
This function returns a new context that shares the same values as the original context but is not subject to cancellation.
Example:
func Handler(ctx context.Context) (interface{}, error) { result := doStuff(ctx) newContext := context.WithoutCancel(ctx) go func() { doSomethingElse(newContext) }() return result }
This way, doSomethingElse will continue running even after the request context has been canceled.
The above is the detailed content of How to Clone a Go Context Without Cancel Propagation?. For more information, please follow other related articles on the PHP Chinese website!