代码之家  ›  专栏  ›  技术社区  ›  Nestor Sokil

无取消传播的上下文

  •  3
  • Nestor Sokil  · 技术社区  · 7 年前

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

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

    func Handler(ctx context.Context) (interface{}, error) {
            result := doStuff(ctx)
            newContext := howDoICloneYou(ctx)
            go func() {
                    doSomethingElse(newContext)
            }()
            return result
    }
    

    有人能告诉我怎么做吗?

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

    2 回复  |  直到 7 年前
        1
  •  14
  •   Peter saif iqbal    7 年前

    由于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}
    }
    
        2
  •  6
  •   Scott Stensland    7 年前

    对不要这样做。

    刚出现的 上下文您的传入上下文和您的后台任务之一是 无关的 因此,您不能尝试重用传入的。

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