go - ctx.Err() vs ctx.Done() chan 关闭检查 : Is there a difference?

标签 go

我处于一个长期运行的可取消函数中,该函数具有一个永久循环。

我需要检查上下文是否关闭。

go func(){
    for {
         if ctx.Err() != nil { return }
         // do work
    }
}()

go func(){
    for {
         select {
            case <-ctx.Done():
                return
            default:
         }
         // do work
    }
}()

这两者有区别吗?

我猜测检查 ctx.Err() 对于并发访问是安全的 https://golang.org/src/context/context.go#L370所以它们看起来是一样的,给定一个封闭的上下文总是会设置 Err。

最佳答案

来自context.Context documentation :

If Done is not yet closed, Err returns nil. If Done is closed, Err returns a non-nil error explaining why

通过扩展,我们可以说您的第一个示例正在检查 Done 是否已关闭。鉴于 done channel 的约定,它们只应关闭,并且永远不会在其上发送任何值,我们可以说您的第二个示例也在检查 Done 是否已关闭。

因此,我们可以说这两个代码示例在功能上是等效的。我们之所以有不同的检查方法是因为每种方法都有一些好处:

  • Err() 是立即检查并给出错误信息。
  • Done() 是一个 channel ,因此可以在 select 情况下等待或使用。

关于go - ctx.Err() vs ctx.Done() chan 关闭检查 : Is there a difference?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67439974/

相关文章:

go - 如何通过 http 提供静态文件

go - 使用 Pop 将数据库中的 JSON 字段编码为结构

go - 调用在 golang 中作为接口(interface)变量接收的函数

go - C 代码是否享受 Go GC 的碎片预防策略?

mongodb - 从 GoLang 中的 mongodb 获取最后插入的元素

go - golang中如何传递变量

api - 使用 golang 服务器的第三方 API 的速率限制

go - 如何在 Golang 上通过 IPC 为 OpenLDAP 客户端实现 SASL/EXTERNAL?

go - 在 golang 中声明具有任意返回类型的函数类型

Go channel 没有死锁或锁定