MST

星途 面试题库

面试题:Go中context如何用于管理多协程任务的取消

请描述在Go语言中,如何使用context来实现多协程任务的取消机制。假设你有多个并发运行的协程执行不同的任务,当外部触发一个取消信号时,这些协程如何优雅地停止工作。请给出具体的代码示例并解释每一步的作用。
40.8万 热度难度
编程语言Go

知识考点

AI 面试

面试题答案

一键面试

在Go语言中,context包提供了一种优雅的方式来实现多协程任务的取消机制。以下是具体的代码示例及解释:

package main

import (
    "context"
    "fmt"
    "time"
)

// 模拟一个长时间运行的任务
func task(ctx context.Context, taskID int) {
    for {
        select {
        case <-ctx.Done():
            fmt.Printf("Task %d received cancel signal, stopping...\n", taskID)
            return
        default:
            fmt.Printf("Task %d is running...\n", taskID)
            time.Sleep(1 * time.Second)
        }
    }
}
func main() {
    // 创建一个可取消的context
    ctx, cancel := context.WithCancel(context.Background())

    // 启动多个协程执行任务
    for i := 1; i <= 3; i++ {
        go task(ctx, i)
    }

    // 模拟5秒后触发取消信号
    time.Sleep(5 * time.Second)
    fmt.Println("Triggering cancel signal...")
    cancel()

    // 等待一段时间,确保所有协程都有机会处理取消信号
    time.Sleep(2 * time.Second)
}

代码解释

  1. context.WithCancel: 创建一个可取消的context,返回一个context.Context和一个取消函数cancelcontext.Background()是所有context的根。
  2. task函数: 每个协程执行的任务。在for循环中,通过select语句监听ctx.Done()通道。当该通道接收到数据时,说明取消信号已触发,协程可以优雅地停止工作。default分支则表示任务在正常运行,这里简单打印任务运行信息并休眠1秒。
  3. 启动协程: 在main函数中,使用go关键字启动多个协程执行task函数,并传入相同的ctx。这样所有协程共享同一个取消信号。
  4. 触发取消: 模拟5秒后调用cancel()函数,这会向所有关联的context发送取消信号,所有监听ctx.Done()的协程都会收到信号并停止工作。
  5. 等待处理: 调用cancel后,等待2秒,确保所有协程有足够时间处理取消信号并安全退出。