Golang 基础 Part 6: Context 包

文章讨论了 context 包在 Golang 中的基础知识、怎样使用 context 包以及使用 context 包的时候需要注意的地方。


Context 包

context 包主要用于父子任务之间的同步取消信号,本质上是一种协程调度的方式。可以通过简化对于处理单个请求的多个 Goroutine 之间与请求域的数据、超时和退出等操作。来看两个例子:

 1package main
 2import(
 3	"context"
 4	"sync"
 5	"fmt"
 6	"time"
 7)
 8// 我们定义一个worker function
 9func worker(ctx context.Context, wg *sync.WaitGroup) error {
10  defer wg.Done()
11
12  for {
13    select {
14    case <- ctx.Done():
15      return ctx.Err()
16    default:
17      fmt.Println("hello")
18    }
19  }
20}
21
22func main(){
23  ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
24
25  var wg sync.WaitGroup
26  for i := 0; i < 10; i++{
27    wg.Add(1)
28    go worker(ctx, &wg)
29  }
30  time.Sleep(time.Second)
31  cancel()
32
33  wg.Wait()
34}
35

当并发体超时或者 main 主动停止 worker goroutine 时,worker goroutine 都可以安全退出。

另外在使用 context 时有两点值得注意:上游任务仅仅使用 context 通知下游任务不再需要,但不会直接干涉和中断下游任务的执行,由下游任务自行决定后续的处理操作,也就是说 context 的取消操作是无侵入的;context 是线程安全的,因为 context 本身是不可变的(immutable),因此可以放心地在多个协程中传递使用。

翻译: