什么是context
Context 是Go 语言独有功能之一,用于上下文控制,可以在 goroutine 中进行传递。
在 Go context 用法中,我们常常将其与 select 关键字结合使用,用于监听其是否结束、取消等
func main() {
Ctx := context.Background()
ctx, cancel := context.WithTimeout(Ctx, 10*time.Millisecond)
defer cancel()
select {
case <-time.After(1 * time.Second):
fmt.Println("overslept")
case <-ctx.Done():
fmt.Println(ctx.Err())
}
在 Go 标准库 context 中具有以下派生 context 的标准方法:
func WithCancel(parent Context) (ctx Context, cancel CancelFunc)
func WithDeadline(parent Context, d time.Time) (Context, CancelFunc)
func WithTimeout(parent Context, timeout time.Duration) (Context, CancelFunc)
context接口
type Context interface {
Deadline() (deadline time.Time, ok bool)
Done() <-chan struct{}
Err() error
Value(key interface{}) interface{}
}
Deadline:获取当前 context 的截止时间。
Done:获取一个只读的 channel,类型为结构体。可用于识别当前 channel 是否已经被关闭,其原因可能是到期,也可能是被取消了。
Err:获取当前 context 被关闭的原因。
Value:获取当前 context 对应所存储的上下文信息。
不要把Context放在结构体中,要以参数的方式进行传递
context.Context的主要作用就是在父子进程(协程)之间进行超时控制、数据传递。作为参数传递可以方便使用者针对不同的函数设置不同的超时时间和要传递的参数。而存储在结构体中,则该结构体的所有方法都会共享该context.Context,适合在定义的struct的生命周期内共享的场景。同时调用者使用时的灵活度会降低。
context 用于简化处理多个 goroutine 之间的数据共享,取消信号,截止时间等操作.
Deadline() (deadline time.Time, ok bool) 方法获取设置的截止时间, 一个参数为截止时间, 到了这个时间 ctx 会自动发起取消请求. 如果没有设置截止时间, 那么需要手动调用 cancel() 方法来停止. ok==false时表示没有设置截止时间 Done() <-chan struct{} 是一个只读的 channel, 返回 struct{}, 当有信号时,表明parent context 已经发起了取消, goroutine 中通过 Done chan 获取到取消信号后, 应当做清理操作,然后退出协程,释放资源 Err() error: 返回 ctx 为什么被取消 Value(key interface{}) interface{} : 获取 ctx 上绑定的值, 通常线程安全
golang context的理解,context主要用于父子任务之间的同步取消信号,本质上是一种协程调度的方式。另外在使用context时有两点值得注意:上游任务仅仅使用context通知下游任务不再需要,但不会直接干涉和中断下游任务的执行,由下游任务自行决定后续的处理操作,也就是说context的取消操作是无侵入的;context是线程安全的,因为context本身是不可变的(immutable),因此可以放心地在多个协程中传递使用。