MST

星途 面试题库

面试题:Go中context取消机制在复杂业务场景下的应用

假设有一个复杂的业务场景,包含多个嵌套的goroutine调用,每个goroutine有不同的任务阶段,当外部触发取消信号时,如何通过context确保所有相关goroutine能正确且有序地取消,并清理各自的资源,请详细描述思路并给出核心代码片段。
11.5万 热度难度
编程语言Go

知识考点

AI 面试

面试题答案

一键面试
  1. 思路
    • 使用 context.Context 来传递取消信号。创建一个 context.Context 和对应的 CancelFunc,当接收到外部取消信号时,调用 CancelFunc
    • 在每个 goroutine 中,定期检查 context.ContextDone 通道,一旦通道可读,说明取消信号已发出,应立即停止当前任务并清理资源。
    • 对于嵌套的 goroutine,将父 goroutinecontext.Context 传递给子 goroutine,这样取消信号可以层层传递。
  2. 核心代码片段
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 完成清理。