channel 模式
go
select {
case v := <-ch:
handle(v)
case <-time.After(time.Second):
return errors.New("timeout")
case <-ctx.Done():
return ctx.Err()
}关闭 channel 表示「不再有值」;接收方用 v, ok := <-ch 判断。
用 errgroup 管理一组 goroutine 生命周期,比裸 channel 更不易泄漏。