面试题答案
一键面试Context常见场景
- 控制子任务的生命周期:在启动多个子任务时,通过Context可以方便地同时取消所有相关子任务。例如在一个Web服务中,处理一个请求可能涉及多个并发的数据库查询、RPC调用等子任务,当请求被取消(如客户端断开连接)时,所有这些子任务都应被取消。
- 设置截止时间:为任务设置一个最长执行时间。比如一个数据库查询操作,希望在1秒内完成,如果超过这个时间就取消操作,防止长时间阻塞。
- 传递请求范围的数据:在不同的函数调用链中传递特定的数据,如用户认证信息、请求ID等,这些数据与请求的整个生命周期相关联。
实现取消操作的代码示例
package main
import (
"context"
"fmt"
"time"
)
func main() {
// 创建一个可取消的Context
ctx, cancel := context.WithCancel(context.Background())
// 启动一个子任务
go func(ctx context.Context) {
for {
select {
case <-ctx.Done():
fmt.Println("子任务被取消")
return
default:
fmt.Println("子任务正在执行")
time.Sleep(1 * time.Second)
}
}
}(ctx)
// 模拟一段时间后取消任务
time.Sleep(3 * time.Second)
cancel()
// 等待子任务完全取消
time.Sleep(1 * time.Second)
}
在上述代码中:
- 使用
context.WithCancel(context.Background())
创建了一个可取消的Context和对应的取消函数cancel
。 - 在子goroutine中,通过
select
语句监听ctx.Done()
通道,当该通道接收到数据时,表示Context被取消,子任务应停止执行。 - 主函数中,通过调用
cancel()
函数来取消Context,进而通知子任务停止执行。