context

Posted by Liao on 2023-02-23

一、简介

go并发编程中,用一个goroutine处理一个任务,而它又会创建多个goroutine来负责不同子任务的场景很常见。这种场景往往需要在api边界之间、过程之间传递截止时间、取消信号、以及其它请求数据(总的来说就是goroutine之间的通信),这时候便可以使用context。

二、使用场景

At Google, we developed a context package that makes it easy to pass request-scoped values, cancellation signals, and deadlines across API boundaries to all the goroutines involved in handling a request.

2.0 创建空的context

1、context.Background()相当于获得根context,该context不能被取消,用在main函数或者顶级请求派生的其它context

1
ctx := context.Background()

2、 context.TODO() 获得一个空context,只能用于不知道context是什么类型的时候

1
ctx := context.TODO() 

2.1传递数据 (请求相关)

1
2
3
4
type valueCtx struct {
Context
key, val any // 支持键值对
}

给context附加一个键值对信息,即可通过context传递数据

1
func WithValue(parent Context, key interface{}, val interface{}) Context

2.2 优雅地取消goroutine

cancelCtx
1
func WithCancel(parent Context) (ctx Context, cancel CancelFunc) // 创建cancelCtx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
func main() {
ctx, cancel := context.WithCancel(context.Background()) // Background()在初始化时获取一个context
defer cancel()
for i := 1; i <= 100; i++ {
go func(i int) {
select {
case <-ctx.Done(): // 收到取消信号,则所有gorouine退出
return
default:
fmt.Println(i)
}
}(i)
}
}
timerCtx
1
2
3
4
5
6
type timerCtx struct { 
cancelCtx
timer *time.Timer // Under cancelCtx.mu.

deadline time.Time
}

创建timerCtx的方式:

1
func WithTimeout(parent Context, timeout time.Duration) (Context, CancelFunc) //时间段
1
func WithDeadline(parent Context, d time.Time) (Context, CancelFunc)  // 时间点

三、参考