テック技報最新号へ →
コード

Go: errgroup.SetLimit で並列数に上限を付ける(自前のセマフォが要らない)

golang.org/x/sync/errgroup の g.SetLimit(n) を呼ぶと、実行中の goroutine が n 個に達した時点で g.Go がブロックする。「同時に n 個まで」と「最初のエラーで残りをキャンセル」を一度に書ける。

@amitsinha__07 · 2026-11-04
#go#concurrency#errgroup#semaphore

使う場面

URL の一覧を並列に取得する、ファイルを並列に処理するなど、件数が多くて全部を同時に走らせると相手や自分のリソースを食い潰すとき。バッファ付きチャネルのセマフォと sync.WaitGroup とエラー集約を自分で組み合わせていたなら、これで置き換えられる。

やり方

go
import (
    "context"

    "golang.org/x/sync/errgroup"
)

func fetchAll(ctx context.Context, urls []string) error {
    g, ctx := errgroup.WithContext(ctx)
    g.SetLimit(8) // 同時に動くのは 8 個まで

    for _, u := range urls {
        g.Go(func() error { // 8 個動いている間はここで待つ
            return fetch(ctx, u) // ctx は最初のエラーでキャンセルされる
        })
    }
    return g.Wait() // 最初に返ったエラー(なければ nil)
}
  • 待たずに諦めたいときは g.TryGo(f) を使う。枠が空いていなければ false を返し、関数は実行されない。
  • Go 1.22 以降はループ変数がイテレーションごとに作られるので、u := u のコピーは不要。

注意点

出典

X の元の投稿を開く