面试题答案
一键面试- 思路:
- 使用
context.Context
来传递取消信号。创建一个context.Context
和对应的CancelFunc
,当接收到外部取消信号时,调用CancelFunc
。 - 在每个
goroutine
中,定期检查context.Context
的Done
通道,一旦通道可读,说明取消信号已发出,应立即停止当前任务并清理资源。 - 对于嵌套的
goroutine
,将父goroutine
的context.Context
传递给子goroutine
,这样取消信号可以层层传递。
- 使用
- 核心代码片段:
package main
import (
"context"
"fmt"
"time"
)
func worker(ctx context.Context, taskID int) {
defer fmt.Printf("Task %d: Resource cleanup\n", taskID)
for {
select {
case <-ctx.Done():
return
default:
// 模拟任务执行
fmt.Printf("Task %d: Working...\n", taskID)
time.Sleep(500 * time.Millisecond)
}
}
}
func main() {
ctx, cancel := context.WithCancel(context.Background())
// 启动多个嵌套的goroutine
for i := 1; i <= 3; i++ {
go func(id int) {
worker(ctx, id)
}(i)
}
// 模拟外部触发取消信号
time.Sleep(2 * time.Second)
cancel()
// 等待所有goroutine完成清理
time.Sleep(1 * time.Second)
fmt.Println("All tasks cancelled and resources cleaned up.")
}
在上述代码中:
context.WithCancel
创建了一个可取消的context.Context
和对应的CancelFunc
。worker
函数模拟了一个带有资源清理的任务,在select
语句中监听ctx.Done()
通道,一旦通道可读,就返回并执行defer
语句清理资源。- 在
main
函数中,启动多个goroutine
,并在一段时间后调用cancel()
模拟外部取消信号,最后等待所有goroutine
完成清理。