没有取消传播的上下文

我如何创建一个 Go 上下文的副本(如果你愿意的话,一个克隆),它包含存储在原始文件中的所有值,但不会在原始文件被取消时被取消?


对我来说,这确实是一个有效的用例。假设我有一个 http 请求,它的上下文在响应返回给客户端后被取消,我需要在这个请求结束时在一个单独的 goroutine 中运行一个异步任务,这个 goroutine 很可能比父上下文活得更久。


func Handler(ctx context.Context) (interface{}, error) {

        result := doStuff(ctx)

        newContext := howDoICloneYou(ctx)

        go func() {

                doSomethingElse(newContext)

        }()

        return result

}

谁能建议应该如何完成?


当然,我可以跟踪所有可能放入上下文中的值,创建一个新的背景 ctx,然后遍历每个可能的值并复制……但这看起来很乏味,而且很难在大型代码库中进行管理。


翻阅古今
浏览 113回答 3
3回答

慕盖茨4494581

由于 context.Context 是一个接口,您可以简单地创建自己的永远不会取消的实现:import (&nbsp; &nbsp; "context"&nbsp; &nbsp; "time")type noCancel struct {&nbsp; &nbsp; ctx context.Context}func (c noCancel) Deadline() (time.Time, bool)&nbsp; &nbsp; &nbsp; &nbsp;{ return time.Time{}, false }func (c noCancel) Done() <-chan struct{}&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;{ return nil }func (c noCancel) Err() error&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; { 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 {&nbsp; &nbsp; return noCancel{ctx: ctx}}

MYYA

谁能建议应该如何完成?是的。不要这样做。如果您需要不同的上下文,例如对于您的异步后台任务,则创建一个新的上下文。您的传入上下文和您的后台任务之一无关,因此您不能尝试重用传入的上下文。如果不相关的新上下文需要来自原始上下文的一些数据:复制您需要的内容并添加新内容。

月关宝盒

从 go 1.21 开始,此功能将通过以下方式直接在标准库中提供context.WithoutCancel:func WithoutCancel(parent Context) ContextWithoutCancel返回 parent 的副本,当 parent 被取消时,该副本未被取消。返回的上下文不返回Deadlineor Err,其Done通道为nil。调用Cause返回的上下文返回nil。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go