You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Goroutine中退出超时任务?代码问题与优化建议咨询

代码问题排查与优化建议

现存问题

  1. run函数无法响应超时中断:当前run函数里的select仅在执行开始时检查一次ctx.Done(),一旦进入default分支执行time.Sleep,即使ctx超时,sleep也会继续执行直到结束,无法及时退出。
  2. goroutine泄漏与退出不优雅:do通道未关闭,导致3个work goroutine会一直阻塞在for v := range do处;main函数用time.Sleep(20s)等待任务完成,属于硬编码等待,无法准确感知任务结束时间。
  3. rand.Seed冗余(Go1.20+):从Go 1.20开始,math/rand包默认会自动初始化随机种子,无需手动调用rand.Seed。

优化后的代码

package main

import (
    "context"
    "log"
    "math/rand"
    "sync"
    "time"
)

func main() {
    s := []int{100, 200, 300, 400, 500, 600}
    do := make(chan int, len(s)) // 改为带缓冲通道,避免发送阻塞
    var wg sync.WaitGroup

    ctx, cancel := context.WithTimeout(context.Background(), time.Second*3)
    defer cancel()

    work := func(ctx context.Context) {
        defer wg.Done()
        for v := range do {
            run(v, ctx)
        }
    }

    workerCount := 3
    wg.Add(workerCount)
    for range [3]struct{}{} {
        go work(ctx)
    }

    // 发送任务到通道,同时监听超时
    for _, v := range s {
        select {
        case do <- v:
        case <-ctx.Done():
            log.Println("ctx timeout, stop sending tasks")
            break
        }
    }
    close(do) // 关闭通道,让work goroutine的for range循环退出

    wg.Wait() // 等待所有worker完成任务
    log.Println("all tasks finished")
}

func run(v int, ctx context.Context) {
    log.Printf("start processing %d", v)
    // 用select同时监听ctx.Done()和任务完成事件
    select {
    case <-ctx.Done():
        log.Printf("task %d timeout", v)
        return
    case <-time.After(time.Duration(rand.Intn(5)+1) * time.Second):
        log.Printf("task %d finished", v)
    }
}

优化说明

  • run函数响应超时:将time.Sleep替换为time.After并放入select分支,这样在任务执行期间一旦ctx超时,<-ctx.Done()会立即触发,任务可以及时退出。
  • 优雅退出与避免泄漏:使用sync.WaitGroup跟踪所有worker goroutine的状态,关闭do通道让worker的for循环正常退出,替代硬编码的time.Sleep。
  • 通道优化:将do改为带缓冲通道,容量等于任务数量,避免main函数在发送任务时因worker未及时接收而阻塞。
  • 任务发送容错:在发送任务时也监听ctx.Done(),如果超时则停止发送剩余任务。

内容的提问来源于stack exchange,提问作者alex

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.02 09:01:04