为了账号安全,请及时绑定邮箱和手机立即绑定

没有取消传播的上下文

没有取消传播的上下文

Go
翻阅古今 2023-06-01 14:24:13
我如何创建一个 Go 上下文的副本(如果你愿意的话,一个克隆),它包含存储在原始文件中的所有值,但不会在原始文件被取消时被取消?对我来说,这确实是一个有效的用例。假设我有一个 http 请求,它的上下文在响应返回给客户端后被取消,我需要在这个请求结束时在一个单独的 goroutine 中运行一个异步任务,这个 goroutine 很可能比父上下文活得更久。func Handler(ctx context.Context) (interface{}, error) {        result := doStuff(ctx)        newContext := howDoICloneYou(ctx)        go func() {                doSomethingElse(newContext)        }()        return result}谁能建议应该如何完成?当然,我可以跟踪所有可能放入上下文中的值,创建一个新的背景 ctx,然后遍历每个可能的值并复制……但这看起来很乏味,而且很难在大型代码库中进行管理。
查看完整描述

3 回答

?
慕盖茨4494581

TA贡献1850条经验 获得超11个赞

由于 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}

}


查看完整回答
反对 回复 2023-06-01
?
MYYA

TA贡献1868条经验 获得超4个赞

谁能建议应该如何完成?

是的。不要这样做。

如果您需要不同的上下文,例如对于您的异步后台任务,则创建一个新的上下文。您的传入上下文和您的后台任务之一无关,因此您不能尝试重用传入的上下文。

如果不相关的新上下文需要来自原始上下文的一些数据:复制您需要的内容并添加新内容。


查看完整回答
反对 回复 2023-06-01
?
月关宝盒

TA贡献1772条经验 获得超5个赞

从 go 1.21 开始,此功能将通过以下方式直接在标准库中提供context.WithoutCancel

func WithoutCancel(parent Context) Context

WithoutCancel返回 parent 的副本,当 parent 被取消时,该副本未被取消。返回的上下文不返回Deadlineor Err,其Done通道为nil。调用Cause返回的上下文返回nil


查看完整回答
反对 回复 2023-06-01
  • 3 回答
  • 0 关注
  • 112 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信