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

取消后是否可以访问 go 上下文值?

取消后是否可以访问 go 上下文值?

Go
人到中年有点甜 2022-08-24 17:22:38
围棋中的学习情境。我尝试了上下文取消,它尝试在取消后访问设置为上下文的值。令我惊讶的是,它奏效了:    import (    "context"    "fmt"    "time")func test(ctx context.Context, cancelFunc context.CancelFunc){    intervalTicker := time.NewTicker(time.Second * 2).C    expiryTicker := time.NewTicker(time.Second * 5).C    for {        select {        case <-ctx.Done():            fmt.Println(ctx.Err())            return        case <-intervalTicker:            fmt.Println("interval")        case <-expiryTicker:            fmt.Println("expiry")            func() {                defer cancelFunc()                fmt.Println("Calling context cancel")            }()            return        }    }}func main() {    type key string    var contextKey key    parent := context.WithValue(context.TODO(), contextKey, "V1")    ctx, cancelFunc := context.WithCancel(parent)    test(ctx, cancelFunc)    fmt.Println(ctx.Value(contextKey))}当我将相同的子上下文和 cancel 函数传递给测试函数时,我本来希望上下文被取消并且值不可用。难道不是这样吗?
查看完整描述

1 回答

?
白猪掌柜的

TA贡献1893条经验 获得超10个赞

上下文中。WithCancel 文档

当调用返回的 cancel 函数或父上下文的 Done 通道时(以先发生者为准),返回上下文的 Done 通道将关闭。

上下文中。上下文文档

Done 返回一个通道,当代表此上下文完成的工作应被取消时,该通道已关闭。

取消上下文不应意味着“销毁此上下文”或“使此上下文不再可用”。这纯粹是向上下文的用户发出信号,表明工作应该被取消。此信号不是魔术,必须明确检查。

请考虑以下情况:

select {

case <-ctx.Done():

    return

default:

    value := ctx.Value("something")

    doSomething(value)

}

现在想象一下,上下文按照您的想象工作,在取消时,值不再可检索。这种情况现在可能是可能的:


select {

case <-ctx.Done():

    return

default:

    // OH NO! Even though we just checked and it was ok,

    // some other goroutine called cancel() right at this moment!

    value := ctx.Value("something")

    // Now "value" is going to be invalid.

    doSomething(value)

}

现有的上下文模型很有帮助,因为它允许工作例程仅在最安全或最方便的特定检查点检查上下文状态,而在其他情况下不必担心它。


查看完整回答
反对 回复 2022-08-24
  • 1 回答
  • 0 关注
  • 116 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号