面试题答案
一键面试1. 使用Context管理并发协程超时控制
在Go语言中,context.Context
主要用于在不同的Go协程之间传递截止时间、取消信号等。以下是如何使用 Context
统一管理并发协程的超时控制,以及处理协程之间依赖关系的步骤:
- 创建带超时的Context:在主程序中,使用
context.WithTimeout
创建一个带超时时间的Context
。这个Context
会在超时时间到达时自动取消。 - 传递Context:将创建的
Context
传递给所有需要管理超时的协程。每个协程在执行任务时,需要检查Context
的取消信号,以便在超时或被取消时及时停止。 - 处理协程依赖关系:对于存在依赖关系的协程,可以通过共享
Context
来确保依赖链上的协程能够同步取消。如果一个协程超时,其依赖的协程也应该通过Context
收到取消信号并停止。
2. 示例代码
package main
import (
"context"
"fmt"
"sync"
"time"
)
// task1 模拟一个任务,依赖于 task2 的结果
func task1(ctx context.Context, wg *sync.WaitGroup, resultChan chan<- string) {
defer wg.Done()
select {
case <-ctx.Done():
fmt.Println("task1: context cancelled, exiting")
return
case result := <-resultChan:
fmt.Println("task1: received result from task2:", result)
// 模拟一些工作
time.Sleep(2 * time.Second)
fmt.Println("task1: completed")
}
}
// task2 模拟另一个任务
func task2(ctx context.Context, wg *sync.WaitGroup, resultChan chan<- string) {
defer wg.Done()
select {
case <-ctx.Done():
fmt.Println("task2: context cancelled, exiting")
return
default:
// 模拟一些工作
time.Sleep(1 * time.Second)
resultChan <- "task2 result"
fmt.Println("task2: completed")
}
}
func main() {
var wg sync.WaitGroup
resultChan := make(chan string)
// 创建带超时的Context
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
defer cancel()
// 启动 task1
wg.Add(1)
go task1(ctx, &wg, resultChan)
// 启动 task2
wg.Add(1)
go task2(ctx, &wg, resultChan)
// 等待所有任务完成
go func() {
wg.Wait()
close(resultChan)
}()
// 等待超时或所有任务完成
select {
case <-ctx.Done():
fmt.Println("main: overall timeout reached")
case <-time.After(5 * time.Second):
fmt.Println("main: all tasks completed within time")
}
}
代码说明
task1
和task2
函数:这两个函数分别模拟不同的任务。task1
依赖于task2
的结果,通过resultChan
接收task2
的结果。在函数内部,使用select
语句监听ctx.Done()
信号,以便在Context
取消时及时退出。main
函数:- 使用
context.WithTimeout
创建一个3秒超时的Context
。 - 启动
task1
和task2
两个协程,并传递Context
和sync.WaitGroup
。 - 使用
sync.WaitGroup
等待所有协程完成,并在所有协程完成后关闭resultChan
。 - 使用
select
语句监听ctx.Done()
信号或等待5秒,以确保在超时或所有任务完成后程序退出。
- 使用
通过这种方式,可以有效地使用 Context
管理并发协程的超时控制,并处理协程之间的依赖关系。