公告

微信

欢迎大家私信交流

Skip to content

context

go的语言特点就是并发。官方为了管理,开发了context包。

context标准库,用来管理goroutine的生命周期,传递上下文,控制超时取消等操作。(非常的就是像总结)

context理解过来就是构建一个上下文链路树,如果某一个链路的节点断了,则子节点会有相应的行为。(自己的理解)

案例学习

假设我们需要从多个api接口中并发的获取数据,如果某个接口超时,就将其请求取消。

context使用

context方法

  • Deadline():返回超时的截止时间
  • Done():上下文完成时或者取消后会调用
  • Err():Done()返回后,使用Err可以获得结束原因
  • Value():获取键值

1.创建根context

context.Background():可以创建一个非nil,空值的Context对象,不能发出取消信号,线程安全,通常作为根Context,用于派生其他Context。

context.TODO(): 和context.Background()一样,一般做为占位符存在。

  • 当一个context被取消,派生的context同样被取消
  • context是线程安全的

2.Value context

context可以在多个goroutines之间传值

context.WithValue()用来在context中存储键值对,它返回一个新的Context,这个新的Context携带了一个键值对。

小结

通过节点 传递键值对

3.Cancel context

通过context.WithCancel创建的context可以发出取消信号

通过取消信号,我们可以终止相关的goroutines,从而避免资源泄露(未能正确释放导致无法回收)

context.WithoutCancel()创建的context在parentContext被取消时,其不会被取消

4.Timeout context

context.WithTimeout用于创建一个带有超时的上下文,这个上下文会在指定的超时时间之后自动取消

注意:如果父 context 有一个截止时间,那么子 context 的截止时间将是父 context 的截止时间和子 context 自己的截止时间中较早的那个

context.WithTimeoutCause()和context.WithTimeout()区别就是错误信息可以自定义

5.Deadline context

context.WithDeadline和context.WithTimeout一样,区别在于时间的表示方式,context.WithDeadline的时间需要时一个具体的时刻

context.WithDeadlineCause()这个函数和WithDeadline用法一样,唯一的区别是可以自定义错误信息

6.AfterFunc context

context.AfterFunc是在parent context完成或者取消后,执行一个函数,会返回一个stop函数,用于停止parent context和func的关联

返回true代表成功取消,false代表context已经完成或者取消。

注意问题

  • 不传递上下文:如果一个函数创建了上下文,但并没有传递给其他函数或协程,这些函数和协程无法响应上下文相关的处理操作
  • 忘记调用取消函数:使用有取消函数的上下文时,记得取消
  • 协程泄露:有上下文的协程需要检查Done channel,当接收到到信号时及时清理资源和退出
  • 过度使用context.Background:没有取消和超时功能,很可能引起问题
  • 传递nil的上下文:不要传递nil的上下文,会导致panic
  • 阻塞调用:应该将阻塞操作(比如IO)包装成使用上下文检查的调用,可以避免被挂起
  • 过度使用上下文:上下文也并不是所有场景都使用,比如处理全局资源或者共享状态等,可能更使用使用锁或者channel
  • 上下文存储在结构体中:应该将context显式的传递给需要的函数,否则可能会引起数据竞态,生命周期管理等问题

源码分析

golang context 上下文这利器--我们要如何看待它

核心接口Context

go
type Context interface {
   // Deadline returns the time when work done on behalf of this context
   // should be canceled. Deadline returns ok==false when no deadline is
   // set.
   Deadline() (deadline time.Timeok bool)
   // Done returns a channel that's closed when work done on behalf of this
   // context should be canceled.
   Done() <-chan struct{}
   // Err returns a non-nil error value after Done is closed.
   Err() error
   // Value returns the value associated with this context for key.
   Value(key interface{}) interface{}
}

上次更新于: