并发范式:`errgroup` + 有界 worker 池

大量任务并发执行,既要限速也要聚合错误。golang.org/x/sync/errgroup 与带缓冲通道可轻松实现:

package main

import (
  "context"
  "fmt"
  "golang.org/x/sync/errgroup"
)

func main() {
  ctx := context.Background()
  g, ctx := errgroup.WithContext(ctx)
  sem := make(chan struct{}, 8) // 8 个并发

  urls := []string{"a","b","c"} // 省略若干

  for _, u := range urls {
    u := u
    g.Go(func() error {
      select {
      case sem <- struct{}{}:
      case <-ctx.Done():
        return ctx.Err()
      }
      defer func(){ <-sem }()
      if err := fetch(ctx, u); err != nil {
        return fmt.Errorf("fetch %s: %w", u, err)
      }
      return nil
    })
  }
  if err := g.Wait(); err != nil { /* 统一上报 */ }
}

func fetch(ctx context.Context, url string) error { return nil }

要点:1)使用 ctx 传递取消;2)信号量通道限制并发;3)g.Wait() 返回首个错误并广播取消;4)避免把大任务塞进单个 goroutine,拆分粒度与外部速率/配额对齐。

评论 0