go中用带缓冲chan模拟future的最轻量可靠解法是make(chan result, 1),缓冲容量必须为1,否则goroutine启动后写入会阻塞,调用方还没来得及接收。

用带缓冲的 chan 模拟 Future 最轻量可靠
Go 没有原生 Future 或 Promise,但用 make(chan Result, 1) 就是标准解法。缓冲容量必须为 1,否则 goroutine 启动后写入会阻塞,调用方还没来得及 就卡死。
- 结果结构体务必含
Err字段,统一成败路径,别拆成两个 channel - 不要在 goroutine 外手动
close()这个 channel——接收方用val, ok := 判断是否送达即可 - 若任务可能超时或需取消,函数签名加
ctx context.Context,并在 goroutine 内部select监听ctx.Done()
并发批量任务结果收集:优先用索引切片 + sync.WaitGroup
要按原始顺序返回结果,别依赖 channel 的发送/接收顺序——它不保证。channel 是无序的,尤其当任务耗时差异大时,range ch 拿到的结果必然错位。
- 预分配
results := make([]Result, len(tasks)),每个 goroutine 明确写入results[i] = res - 闭包里循环变量
i必须显式重绑定:for i := range tasks { i := i; go func() { results[i] = ... }() } - 用
sync.WaitGroup等待全部写入完成,不用关 channel、不涉及排序、无数据竞争风险
HTTP handler 里启动 goroutine 的致命陷阱
在 handler 函数里直接写 go process(r) 是生产环境高频崩溃源头,不是异步,是埋雷。
-
r.Body在 handler 返回后立即被关闭,goroutine 里再io.ReadAll会读到空或 panic - 没做并发控制,突发流量会瞬间拉起成千上万 goroutine,打爆内存或 DB 连接池
- goroutine 内 panic 不会向 handler 传播,日志里完全无声,问题难定位
- 进程重启时所有未执行 goroutine 彻底丢失,任务静默消失
错误传递别用裸 error channel,封装结构体更可控
只传 chan error 会丢失上下文:哪个任务失败?输入参数是什么?失败时其他任务是否该中止?
- 定义
type TaskResult struct { ID string; Data interface{}; Err error },带上标识和原始输入线索 - 多个任务共用一个
chan TaskResult,主协程用select配合context.WithTimeout控制整体超时 - 避免用
errgroup.Group替代结果收集——它只管错误聚合和等待,不管结果存哪、怎么排序、是否成功
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











