Context
默认上下文
context.Background
是上下文的默认值,所有的其他上下文都应该从它衍生出来context.TBDO
应该仅在不确定使用哪种上下文的时候使用
取消信号 context.WithCancel
-
源码分析
func WithCancel(parent Context) (ctx Context, cancel CancelFunc) { // 将传入的上下文包装成私有结构体 context.cancelCtx; c := newCancelCtx(parent) // 构建父子上下文之间的关联,当父上下文被取消时,子上下文也会被取消: propagateCancel(parent, &c) return &c, func() { c.cancel(true, Canceled) } }
-
衍生出一个新的子上下文并返回用于取消该上下文的函数。一旦执行返回的取消函数,当前上下文以及它的子上下文都会被取消,所有的
Goroutine
都会同步收到这一取消信号。可以用
defer cancel()
配合当取消信号发送后,所有的
ctx
的协程应该尽快推出
传值方法 context.WithValue
- 使用
context.WithValue
来传递所有请求参数是一种很差的设计 - 常见的使用场景是传递请求的用户认证信息或者进行链路追踪的请求ID
带有截止日期的上下文 context.WithDeadline
-
案例
deadline := time.Now().Add(10 * time.Second) // 10秒后的时间 ctx, cancel := context.WithDeadline(context.Background(), deadline) defer cancel() // 在函数退出时调用 cancel 函数
-
当截止日期到达时,Context 会自动发送一个取消信号。
带有超时时间的上下文 context.WithTimeout
-
案例
ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second) defer cancel()
-
当超时时间到达时,Context 会自动发送一个取消信号。
用途总结
控制请求的超时时间
- 在请求处理过程中设置一个超时时间,以确保在该时间之内完成处理,避免请求被挂起或者阻塞。
- 如果超时时间到期,我们可以通过上下文的超时机制来取消请求处理,并立即返回错误信息给客户端。
传递请求范围内的值
处理请求取消
- 在HTTP请求处理中,如果客户端提前关闭了连接,服务器可以通过上下文来判断是否取消请求
实现并发控制
- 在一个多任务并发执行的程序中,为每个任务创建一个上下文,
- 在每个任务执行之前检查上下文的状态
- 如果上下文已经取消或者超时,则立即停止该任务的执行,从而实现并发控制
实现请求跟踪
- 在每个请求处理中创建一个唯一的请求ID,并将其存储在上下文中。
- 将该请求ID传递给所有相关的组件,从而跟踪整个请求的处理过程。