Go语言中context 结构原理?说一说context 使用场景和用途?
在Go语言中,context
是一个非常重要的概念,它为我们提供了在跨API边界和进程之间传递请求作用域的deadline,取消信号,和其他请求相关的值的能力。
context
包定义了Context
类型,它在API边界和进程之间提供了一种传递deadline,取消信号,和其他请求相关的值的方式。一个Context
的生命周期通常与请求处理的生命周期相同,并且可以包含在多个API调用和goroutines之间共享的数据和取消信号。
context
的主要方法有:
Deadline
:返回当前Context
何时会被取消。如果Context
不会被取消,则返回ok为false。Done
:返回一个通道,当Context
被取消或超时时,该通道会被关闭。Err
:返回Context
为何被取消。Value
:返回与Context
相关的值,这些值必须是线程安全的。
Go语言的context
包提供了两个函数用于创建Context
对象:context.Background()
和context.TODO()
,前者通常用在主函数、初始化以及测试代码中,表示一个空的Context
,后者通常用在不确定应该使用什么Context
,或者函数以后会更新以便接收一个Context
参数。
此外,context
包还提供了WithCancel
,WithDeadline
,WithTimeout
和WithValue
函数,用于从现有的Context
派生出新的Context
。
context
的主要使用场景有:
- 超时控制:我们可以通过
context.WithTimeout
创建一个超时的Context
,当超时时间到达,该Context
就会自动取消。 -
请求传递:在微服务或者并发编程的环境中,我们可以通过
context.WithValue
将请求相关的数据绑定到Context
中,在函数调用链路上下游之间传递。 -
请求取消:我们可以通过
context.WithCancel
或context.WithTimeout
创建一个可被取消的Context
,并在需要取消时调用Context
的cancel
函数。
以下是一个例子展示了如何使用context
来控制超时:
func main() {
// 创建一个超时时间为1秒的Context
ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second)
defer cancel() // 在函数返回时取消Context
select {
case <-time.After(2 * time.Second):
fmt.Println("overslept")
case <-ctx.Done():
fmt.Println(ctx.Err()) // context deadline exceeded
}
}
在这个例子中,我们设置了一个1秒的超时,当超时时间到达,ctx.Done()
通道就会接收到一个信号,从而触发超时处理。