- A+
context.Context是Golang标准库提供的接口(context包对此接口有多种实现),该接口提供了四个抽象法:
type Context interface {
Deadline() (deadline time.Time, ok bool)
Done() <-chan struct{}
Err() error
Value(key any) any
}
Deadline方法,返回context.Context被取消的时间点,也就是需要完成任务的截止时间,连续调用返回相同的结果。
Done方法, 当前context被取消后,返回的channel就会被close。如果当前context不会被取消则返回nil,连续调用返回相同的结果。
Err方法,返回context.Context结束的错误
如果Done方法返回的channel没有关闭,返回nil
如果Done方法返回的channel被关闭了,返回一个非nil的值,连续调用返回相同的结果
context如果被取消了,返回 “context canceled”错误
如果执行时间超过了Deadline,返回 “context deadline exceeded”错误
Value方法,返回Context中key对应的value值,对于同一个context,多次调用获取同一个key的值会返回相同的结果。
如何构造context.Context对象?
context包提供了两个方法:
func Background() Context{}
func TODO() Context {}
Background方法,返回一个空Context对象,所有Context对象的的源头都应该是这个空Context对象。
TODO方法,也是返回一个空Context对象,如果还不确定使用何种Context时,可以使用此方法创建的Context对象。
目前context.Background和context.TODO方法没有太大差别,返回的都是空Context,只是在使用场景和语义上稍有不同。其他的Context都需要基于构造好的Context衍生出来,一个Context可以衍生多个子Context。
衍生Context方法
context包提供如下四个以With开头的衍生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)
func WithValue(parent Context, key, val any) Context
前三种方法的相同点都是基于parent Context生成一个新的Context并返回一个CancelFunc方法,CancelFunc调用后,当前Context和基于新Context的子Context都会被取消。不同点在于WithCancel方法返回的CancelFunc需要手动调用;WithDeadline方法可以设置一个时间点,到这个时间点后会自动调用CancelFunc,当然也可以手动调用;WithTimeout方法可以设置时长,超过指定时长后会自动调用CancelFunc,当然也可以手动调用。
WithValue方法可以生成一个绑定指定的键值对数据的Context,可以通过context.Value(Key) 获取指定key的值。
使用context包需要注意的点
需要Context参数的方法,把Context作为第一个参数(千万不要把Context放在结构体中,然后将结构体作为参数传递)。
使用context.Background方法构造的Context对象应该作为根Context, 用于衍生其他Context。
方法需要传入的Context类型不确定的时候,传入使用context.TODO构造的Context (千万不要传入nil)。
不要滥用context.WithValue传递数据,只用来传递必须的数据。
Context是并发安全的,同一个Context可以传递给多个goroutine,可被多个goroutine同时访问。
- 我的微信公众号
- 扫一扫关注
- 我的新浪微博号
- 扫一扫关注