Go语言中的上下文(Context)是一种用于在 Goroutines 之间传递取消信号、截止时间和其他请求范围值的标准方式。context
包提供了 Context
类型和一些相关的函数,用于在并发程序中有效地传递上下文信息。
在Go语言中,上下文通常用于以下场景:
通过使用上下文,可以有效地在 Goroutines 之间传递取消信号、截止时间和请求范围的值,从而更好地控制并发程序的行为。
context.Context
接口Context
接口定义了在 Goroutines 之间传递的上下文的基本方法:
type Context interface {
Deadline() (deadline time.Time, ok bool)
Done() <-chan struct{}
Err() error
Value(key interface{}) interface{}
}
ok
为 true
,否则为 false
。nil
。key
关联的值。这允许在上下文中传递请求范围的数据。在 Go 中,上下文可以通过 context.Background()
创建,它是一个无值的上下文,通常用作根上下文。根上下文不能被取消,也不能传递截止时间。
ctx := context.Background()
可以使用 context.WithCancel
、context.WithTimeout
、context.WithDeadline
和 context.WithValue
等函数创建派生上下文,这些函数分别用于创建带有取消、超时、截止时间和值的上下文。
// 创建一个带有取消功能的上下文
ctx, cancel := context.WithCancel(context.Background())
// 创建一个带有超时的上下文
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
// 创建一个带有截止时间的上下文
deadline := time.Now().Add(2 * time.Second)
ctx, cancel := context.WithDeadline(context.Background(), deadline)
// 创建一个带有值的上下文
key := "key"
value := "value"
ctx := context.WithValue(context.Background(), key, value)
在 Go 中,通过函数参数将上下文传递给调用的函数,从而使调用的函数能够感知上下文的取消或超时。例如:
func myFunction(ctx context.Context) {
// 在这里使用 ctx 处理逻辑
select {
case <-ctx.Done():
// 上下文被取消,执行清理工作
fmt.Println("Context canceled")
return
default:
// 继续正常的逻辑
fmt.Println("Doing some work")
}
}
func main() {
// 创建带有取消功能的上下文
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
// 启动 Goroutine,传递上下文
go myFunction(ctx)
// 主 Goroutine 执行一些工作
time.Sleep(2 * time.Second)
}
调用 cancel()
函数会取消与上下文相关的 Goroutines。一旦上下文被取消,与之关联的所有 Goroutines 都会收到取消信号。
ctx, cancel := context.WithCancel(context.Background())
// 启动 Goroutine,传递上下文
go func(ctx context.Context) {
select {
case <-ctx.Done():
// 上下文被取消,执行清理工作
fmt.Println("Context canceled")
return
}
}(ctx)
// 取消上下文
cancel()
使用 context.WithTimeout
或 context.WithDeadline
函数可以设置上下文的超时或截止时间。当超过指定的时间后,上下文会自动取消。
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
defer cancel()
// 启动 Goroutine,传递上下文
go func(ctx context.Context) {
select {
case <-ctx.Done():
// 上下文超时,执行清理工作
fmt.Println("Context timeout")
return
}
}(ctx)
// 主 Goroutine 执行一些工作
time.Sleep(3 * time.Second)
context.WithValue
函数可以用于在上下文中传递请求范围的值。这些值可以通过 context.Value
方法在上下文中检索。
ctx := context.WithValue(context.Background(), "user", "john_doe")
// 从上下文中获取值
value := ctx.Value("user")
fmt.Println(value) // 输出: john_doe
可以通过链式调用的方式,将多个上下文进行组合,形成一个父子关系的上下文链。
parentCtx := context.Background()
ctx1, cancel1 := context.WithTimeout(parentCtx, 2*time.Second)
defer cancel1()
ctx2, cancel2 := context.WithCancel(ctx1)
defer cancel2()
上述的 ctx2
是 ctx1
的子上下文,当 ctx1
超时或被取消时,ctx2
也会相应地被取消。
我正在参与2023腾讯技术创作特训营第三期有奖征文,组队打卡瓜分大奖!
声明:本作品采用署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0)进行许可,使用时请注明出处。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。