面试题答案
一键面试- Context的传递:
- 在Go中,
context.Context
通常作为函数参数在不同的函数之间传递,特别是在启动子定时任务的函数中。 - 可以使用
context.Background()
作为根上下文,然后基于这个根上下文衍生出带取消功能的上下文。
- 在Go中,
- 取消逻辑:
- 使用
context.WithCancel
函数创建一个可取消的上下文。该函数返回一个新的上下文和一个取消函数。当需要取消所有子定时任务时,调用这个取消函数。 - 在每个子定时任务的循环中,定期检查上下文的
Done
通道。如果Done
通道接收到数据,说明上下文已被取消,子任务应立即停止。
- 使用
- 资源清理:
- 子任务在接收到取消信号后,应负责清理自己占用的资源,比如关闭文件描述符、数据库连接等。
- 可以使用Go语言的
defer
语句来确保资源在函数结束时被正确清理。
以下是核心代码片段:
package main
import (
"context"
"fmt"
"sync"
"time"
)
func subTask(ctx context.Context, taskID int, wg *sync.WaitGroup) {
defer wg.Done()
for {
select {
case <-ctx.Done():
// 清理资源
fmt.Printf("Task %d cancelled\n", taskID)
return
default:
// 模拟子任务工作
fmt.Printf("Task %d working\n", taskID)
time.Sleep(time.Second)
}
}
}
func main() {
ctx, cancel := context.WithCancel(context.Background())
var wg sync.WaitGroup
numTasks := 3
for i := 0; i < numTasks; i++ {
wg.Add(1)
go subTask(ctx, i, &wg)
}
// 模拟特定条件触发取消
time.Sleep(3 * time.Second)
cancel()
// 等待所有子任务完成
wg.Wait()
fmt.Println("All tasks completed or cancelled")
}
在上述代码中:
context.WithCancel
创建了一个可取消的上下文ctx
和取消函数cancel
。subTask
函数在循环中通过select
语句监听ctx.Done()
通道,一旦接收到取消信号,就进行资源清理并返回。- 在
main
函数中,启动了多个子任务,并在特定条件下(这里是3秒后)调用cancel
函数取消所有子任务,最后通过wg.Wait()
等待所有子任务完成。