Nes*_*kil 4 asynchronous go goroutine cancellation
如何创建包含原始文件中存储的所有值的Go上下文的副本(如果愿意,则为克隆),但在原始文件中不会被取消?
它似乎对我来说是一个有效的用例.假设我有一个http请求,并且在将响应返回给客户端后取消其上下文,并且我需要在单独的goroutine中在此请求的末尾运行异步任务,该任务很可能比父上下文更长.
func Handler(ctx context.Context) (interface{}, error) {
result := doStuff(ctx)
newContext := howDoICloneYou(ctx)
go func() {
doSomethingElse(newContext)
}()
return result
}
Run Code Online (Sandbox Code Playgroud)
任何人都可以建议如何做到这一点?
当然,我可以跟踪可能放入上下文的所有值,创建一个新的后台ctx,然后只是迭代每个可能的值并复制......但这似乎很乏味,很难在大型代码库中进行管理.
从 go 1.21 开始,可以通过以下方式在标准库中直接使用此功能context.WithoutCancel:
func WithoutCancel(parent Context) Context
Run Code Online (Sandbox Code Playgroud)
WithoutCancel返回父级取消时未取消的父级副本。返回的上下文返回 noDeadline或Err,其Done通道为nil。调用Cause返回的上下文会返回nil。
由于context.Context是一个接口,因此您可以简单地创建自己的实现,该实现永远不会被取消:
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) }
// WithoutCancel returns a context that is never canceled.
func WithoutCancel(ctx context.Context) context.Context {
return noCancel{ctx: ctx}
}
Run Code Online (Sandbox Code Playgroud)
任何人都可以建议如何做到这一点?
是.不要这样做.
如果需要不同的上下文,例如,对于异步后台任务,则创建新上下文.您的传入上下文和后台任务之一是无关的,因此您不能尝试重用传入的上下文.
如果不相关的新上下文需要原始数据:复制您需要的内容并添加新内容.