go - 没有取消传播的上下文

标签 go asynchronous goroutine cancellation

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

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

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

有人可以建议应该如何完成吗?

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

最佳答案

由于 context.Context 是一个接口(interface),您可以简单地创建您自己的永不取消的实现:

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

关于go - 没有取消传播的上下文,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54128834/

相关文章:

c# - 运行异步任务并调用 winform 控件

goroutine 从具有动态循环的 channel 读取 WaitGroup 在返回之前被重用

go - 为什么Goroutines与顺序执行所花的时间几乎相同?

testing - Golang coverprofile 输出格式

c# - 到 Task.Run 或不到 Task.Run

c++ - 嵌套 Lambda 函数 - 性能影响

select - 了解使用和不使用 goroutine 从 channel 中选择

go - 在 Go 中重新连接到 Redis 订阅的惯用方法是什么?

json - 自定义时间。时间类型返回到数据存储区

go - panic 和断言有什么区别?