Go语言怎么做任务队列_Go语言后台任务队列教程【经典】
用无缓冲channel做任务队列易卡死,因未分离投递与执行节奏;需设缓冲(如make(chan Task, 100))并配协程池消费,否则生产快、消费慢即阻塞。Go 用 channel 做简单任务队列,为什么容易卡死?直接用 chan 实现任务分发,不加缓冲或控制并发,很快就会阻塞在 send 或 recv。根本原因是:没有分离「投递」和「执行」节奏,生产者一快、消费者一慢,整个流程就停住。别用无缓冲 chan 接收外部请求——taskCh := make(chan Task) 是典型陷阱至少设缓冲:taskCh := make(chan Task, 100),但缓冲不是万能解,只是买点时间必须配工作协程池,比如 for i := 0; i ,否则没人消费记得在 worker 里用 for task := range taskCh,别只读一次就退出要不要上 redis 或 asynq?看这三点本地 channel 只适合单进程、短生命周期、不关心失败重试的场景。一旦要持久化、多实例、延时任务或失败告警,就得换方案。如果任务丢了不能接受(比如支付回调),channel 不行,必须用 redis + asynq 或 machineryasynq 的 Client 和 Server 分离清晰,但默认不开启 redis 密码认证,上线前得配 asynq.RedisConnOpt{Password: "xxx"}用 asynq 时,任务结构体字段必须是导出的(首字母大写),否则序列化后丢失:type SendEmailTask struct { To string `json:"to"` },不是 to stringtime.AfterFunc 能当延时队列用吗?能,但仅限秒级、低频、不关心准确性的临时需求。它本质是单次定时器,没队列语义,也不支持取消已排队但未触发的任务。time.AfterFunc(5 * time.Second, func() { doWork() }) —— 这个调用完就返回,无法获取句柄想取消?得自己包一层:timer := time.NewTimer(5 * time.Second); go func() { ,然后用 <code>timer.Stop()高并发下大量 time.AfterFunc 会撑爆 runtime.timer 内存,压测时注意 GODEBUG=gctrace=1 观察用 sync.WaitGroup 等所有任务结束,为什么有时候不生效?常见于协程启动后立即 wg.Wait(),但 wg.Add() 没在协程外提前调好,或者 wg.Done() 被 panic 绕过。 Zeemo AI 一款专业的视频字幕制作和视频处理工具
