【发布时间】:2022-08-22 11:46:16
【问题描述】:
相对较新的 Go 用户,来自 C 和 Python。试图理解上下文,我一直在等待一些神奇的解释来点击,最后对自己说,“哦,这似乎真的很有用”,但每次我看到示例和用法时,它似乎都是一个非常基本的“全局”标志表示已打包并卡入标准库的状态。
我错过了一些关于上下文的特别之处吗?
我觉得两个主要用例是:
-
传递任意用户数据(void *usersata 或 def function(args, udata={}))。
-
更有用的情况是取消/超时。典型的例子是使用计时器或其他东西来检查它是否在 goroutine 中完成:
const interval = 500 func main() { ctx, cancel := context.WithCancel(context.Background()) go func() { time.Sleep(5 * interval * time.Millisecond) cancel() }() f(ctx) } func f(ctx context.Context) { ticker := time.NewTicker(interval * time.Millisecond) for { select { case <-ticker.C: doSomething() case <-ctx.Done(): return } } } func doSomething() { log.Println(\"tick\") }我明白了,但这是否意味着每个上下文感知函数都在执行这个 for-select 循环以支持检测取消?我有点期待一些内置的围棋魔术。这与任何其他全局标志/互斥体/goroutine 可以检查的任何东西有什么不同
if globalFlag == CANCELLED此外,在我看到的上下文描述中,“支持通知长时间运行的进程不再需要继续”。然而,这个想法只适用于你的长时间运行的过程实际上是多个可以在 for-select 循环中迭代的东西。同步/阻塞过程永远不能真正被取消,可以吗?如果我有一个长时间运行的 mysql 查询,上下文不会神奇地给我一些方法来断开 mysql 连接并放弃它吗?
mysql.Query(\"SELECT SLEEP(500)\")无法取消,因为在 Query 实际返回之前,我无法围绕它运行选择循环。我是正确理解上下文还是我错过了一些重要的东西?
-
包 mutex+variable 不可用或与其他包 API 标准化,并且不允许诸如选择多个通道之类的事情。是的,您可以“只是”通过其他方式做到这一点——上下文只是对其功能的方便包装,我们多年来一直没有它们,然后它们是通过外部包实现的。
-
它不是一个全局标志,因为它是明确传递的,这肯定是一件好事。没有魔法全球。
-
选择语句不是检查取消的唯一方法。您还可以检查Context.Err 的返回值。数据库查询绝对可以被中断,至少通过简单地关闭网络连接(如果内存可用,这就是 MySQL 驱动程序所做的)。
-
\"这个想法只适用于你的长时间运行的过程实际上是多个可以在 for-select 循环中迭代的东西。\"。这是不正确的。在 select 语句之外,您可以使用
Err方法检查上下文是否关闭。您可以在整个非循环任务中的任何时间点任意执行此操作。
标签: go