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
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.Time, ok 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{}
}