金色财经转发报道:


介绍

context 是整个 Go 生态系统的关键部分。在这篇简短的文章中,我将解释 context 在 Go 应用程序中是如何工作的。

概述

从非常高级的角度来看,可以将 Context 与n叉树数据结构进行比较。查看下图:

在本文中,我将只考虑最有意思的 Go context WithCancel。

带有取消的 context

当向 context 上下文发出取消信号时,所有监听上下文的goroutine都会被中断。如果父上下文发出了取消信号,那么从父上下文派生的所有子上下文也收到取消信号,因此所有监听上下文(父上下文和子上下文)的 goroutine 都会被中断。

好的。让我们查看使用场景。

场景 1

上图中发生了什么?

  • Goroutines 1,2和3使用相同的 context。
  • Goroutines 2 & 3 正在使用<-ctx.Done通道监听上下文中的任何取消信号。
  • Goroutine 1 发出了取消信号,goroutines 2 和 3 立即被中断。

场景 2

现在,让我们检查一个不同的场景。

  • Goroutine 1 在与 goroutines 2 & 3 不同的环境中工作。
  • goroutines 2 & 3 的上下文不是从goroutine 1的上下文派生的。
  • 现在,如果 goroutine 1 发出取消事件,goroutines 2 和 3 会被中断吗?

答案是否定的。

场景 3

  • Goroutine 1 在与 goroutines 2 & 3 不同的环境中工作。
  • goroutines 2 & 3 的上下文是从 goroutine 1 的上下文派生的。
  • 现在,如果 goroutine 1 发出取消事件,goroutines 2 和 3 会被中断吗?

答案是肯定的。

场景 4

  • 如果为根上下文发出取消事件会发生什么?

那么,在这种情况下,所有的 goroutine 都会被中断。

看一些代码

下面是我在图形中的代码逻辑。

我有两个阶段,第一阶段和第二阶段。我从根上下文派生的阶段 1 创建了ctxCancelStage1 。现在,我为阶段 2 创建了另一个从ctxCancelStage1派生的上下文ctxCancelStage2 。第 1 阶段正在生成有关通道数据的一些数据,第 2 阶段正在从同一通道读取数据。阶段 1 正在为ctxCancelStage1发出取消信号,因此,阶段 2中的 goroutine (worker)正在监听事件并进行相应的处理。在演示代码中,它只是退出循环以停止处理数据。

在执行代码时,您应该会看到以下输出。

现在,让我们稍微调整一下代码。

在这里,我创建了从根上下文派生的ctxCancelStage2。第 2 阶段正在处理这种情况。在ctxCancelStage1上触发了取消事件。第二阶段会被打断吗?答案是否定的。在演示代码中,阶段 2中的worker继续无限循环。(内存泄漏)。下面是结果。

结论

在这篇简短的文章中,我解释了 Go 中 Context 的用例。我发现它在处理并发请求时非常有用。希望这篇文章能帮助我们弄清楚 Go context 上下文是如何工作的。




推荐阅读以下标签: