MST

星途 面试题库

面试题:Go中如何使用Channel与Context来实现任务取消

请描述在Go语言中,怎样结合Channel和Context来实现一个可以被取消的任务。假设你有一个函数 `func longRunningTask(ctx context.Context, ch chan int)`,该函数在执行一些长时间运行的计算,并通过 `ch` 通道返回结果,当 `ctx` 被取消时,函数应立即停止计算并清理资源,用代码示例说明实现过程。
36.8万 热度难度
编程语言Go

知识考点

AI 面试

面试题答案

一键面试
package main

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

func longRunningTask(ctx context.Context, ch chan int) {
    defer close(ch)
    for i := 0; ; i++ {
        select {
        case <-ctx.Done():
            // 清理资源,例如关闭文件、数据库连接等
            fmt.Println("任务被取消,清理资源")
            return
        default:
            // 模拟长时间运行的计算
            time.Sleep(100 * time.Millisecond)
            ch <- i
        }
    }
}

func main() {
    ctx, cancel := context.WithTimeout(context.Background(), 500*time.Millisecond)
    defer cancel()

    ch := make(chan int)
    go longRunningTask(ctx, ch)

    for result := range ch {
        fmt.Println("收到结果:", result)
    }
    fmt.Println("任务结束")
}

在上述代码中:

  1. longRunningTask 函数接受一个 context.Context 和一个 chan int。在函数内部使用 select 语句监听 ctx.Done() 信号,当 ctx 被取消时,ctx.Done() 通道会接收到数据,从而可以停止计算并清理资源。
  2. main 函数中,使用 context.WithTimeout 创建一个带有超时的 context,并启动 longRunningTask 协程。for... range 循环从 ch 通道中接收数据,当 ch 通道关闭时(longRunningTask 函数结束),循环结束。同时,通过 cancel 函数可以手动取消 ctx,在这个例子中是由超时自动触发取消。