context.Context 是 Golang 在标准库中提供的一个重要接口。它主要用于在远程调用或接口中传递截止时间、取消信号等上下文信息。
context.Context 主要有以下几个作用:
- 在一个树结构中传播上下文,用于多 goroutine 之间的超时控制、取消信号等;
- 定时器,获取一个上下文可能被取消的截止时间;
- 传播用户定义的 request-scoped 数据;
Context 接口定义如下:
type Context interface {
// Deadline返回当前上下文被取消的时间,如果没有设置截止时间会返回一个ok值false
Deadline() (deadline time.Time, ok bool)
// Done返回一个Channel,当这个上下文被取消或超时的时候会关闭该Channel
Done() <-chan struct{}
// Err返回当前上下文结束的原因,它只会在Done返回的Channel被关闭的时候有效
Err() error
// Value返回与键绑定的值,主要用于传递请求域数据
Value(key interface{}) interface{}
}
我们通常不会直接定义 Context 类型,而是使用标准库中提供的几种实现:
- context.Background():空上下文,所有新的上下文都是从这个开始的。
- context.TODO():推迟使用具体的上下文,目前还不清楚使用什么上下文。
- context.WithCancel(parent):从父上下文派生一个可取消的子上下文。
- context.WithDeadline(parent, deadline):从父上下文派生一个到期时间的子上下文。
- context.WithTimeout(parent, timeout):从父上下文派生一个带超时的子上下文。
- context.WithValue(parent, key, val):从父上下文派生一个携带值的子上下文。
例如:
// WithCancel
ctx, cancel := context.WithCancel(context.Background())
doSomething(ctx, ...)
// 取消操作
cancel()
// WithDeadline
ctx, _ := context.WithDeadline(context.Background(), time.Now().Add(50*time.Millisecond))
select {
case <-ctx.Done():
// 处理超时...
case <-时间到:
}
// WithValue
ctx := context.WithValue(context.Background(), key, value)
// 在其他goroutine中获取值
value := ctx.Value(key)
所以总结来说,context.Context 提供了一种在程序调用的不同层传递截止时间、取消信号和其它请求域数据的方式。这使得我们可以更加灵活和模块化地设计 API。
context 包正在慢慢成为 Golang 标准库中另一个至关重要的包,它彻底解决了 Golang 作为服务端语言在复杂系统或服务中的并发与接口超时控制等问题。