Go言語

Goで学ぶ並行処理と並列処理の実務ベストプラクティス

ⓘ本ページはプロモーションが含まれています

お得なお知らせ

スポンサードリンク
AI時代のキャリア構築

プログラミング学習、今日から動き出す

「何から始めるか」で止まっている人こそ、無料説明会や本で自分に合うルートを30分で確定できます。

Enjoy Tech!|月額制でWeb系に強い▶ (Kindle本)ITエンジニアの転職学|後悔しないキャリア戦略▶

▶ AIコーディング環境なら  実践Claude Code入門(Amazon)が実務で即使える入門書です。Amazonベストセラーにも選ばれていますよ。


スポンサードリンク

並行処理と並列処理の違い

概念整理

用語 定義 主な利用シーン
Concurrency(並行処理) 複数タスクを 設計上 同時に進めること。スレッド数が足りなくても、実装は単一スレッドで動くことがある。 I/O 待ちやユーザー入力の同時受付
Parallelism(並列処理) 複数タスクを 物理的に 同時に実行すること。CPU コアが複数あれば、OS スレッドがそれぞれ別コアで走る。 CPU バウンドな計算・画像加工

Go のランタイムは M:N スケジューラG = goroutine, M = OS スレッド, P = 実行単位)を採用しており、並行 に書いたコードは実行時に自動で 並列 にスケジュールされます。

Qiita 記事「【Go 入門】 Goで並列処理を体感してみよう」でも同様の図解が掲載されています。
https://qiita.com/manabito76/items/448b77e2fc557016eadf

実務上のポイント

  • タスク分割並行 設計で考える(「何を同時にやるか」)。
  • CPU 数に応じた runtime.GOMAXPROCS の設定だけで、ランタイムが最適な 並列 実行へ切り替わります。

goroutine の基礎

1. goroutine の作成

  • go キーワードひとつで 非同期 に実行でき、スタックサイズやスケジューリングはランタイムが自動管理します。

2. スタックサイズの自動拡張

項目 内容
初期サイズ 2 KB(Go 1.22 では 2 KB)
最大上限 1 GB(公式ドキュメント: https://go.dev/ref/spec#Size_and_alignment_of_variables に記載)
拡張方式 必要に応じて 倍増 し、不要になれば縮小される(「スプリット」アルゴリズム)

ポイント: 開発者がスタックサイズを意識する必要はほぼありません。メモリ使用量が気になる場合は runtime.Stack で実行時のスタック情報を取得できます。


channel と select の活用法

1. バッファ有無(unbuffered vs buffered)

  • unbuffered は「通信相手が揃うまで待つ」ことでレースコンディションを防止。
  • buffered はスループット向上とバックプレッシャー制御に有効。

2. 方向限定チャネル

  • chan<-(送信専用)と <-chan(受信専用)は API の安全性 を高め、誤ったデータフローをコンパイル時に検出できます。

3. select 文でマルチチャネル待ち合わせ & タイムアウト

  • select複数の待ちタイムアウト/キャンセル をシンプルに記述でき、デフォルトケース (default) の有無で「ノンブロッキング」かどうかを制御できます。

同期・キャンセル機構

1. sync.WaitGroup と sync.Mutex

  • WaitGroupタスク完了の集合的監視Mutex共有リソースへの排他制御 を提供します。

2. context パッケージでキャンセルとデッドライン管理

  • context.WithCancel, WithTimeout, WithDeadline階層的にキャンセル情報を伝搬 し、長時間走る goroutine のリーク防止に必須です。

代表的な並行パターン

1. Worker Pool(固定数ワーカー)

  • 利点: 同時実行数を一定に保ち、CPU コア数と合わせてリソース消費の上限が予測しやすい。

2. Fan‑out / Fan‑in(分散 & 集約)

  • fan‑out: 複数の goroutine にタスクを分散させ、I/O 待ち時間を相殺。
  • fan‑in: 結果を 1 本のチャネルに集約し、呼び出し側は単一受信で完結。

3. Pipeline(ステージング)

  • 特徴: 各ステージが独立して動作できるため、保守性とスループットが向上。
  • 実装ポイント: ステージ間は必ずチャネルで接続し、close によって下流へ終了シグナルを伝搬させる。

Go 1.22 の新機能と実務ベストプラクティス

1. errgroup パッケージの現状(誤解の訂正)

Go 1.22 でも golang.org/x/sync/errgroupAPI は変更されていません
- 従来どおり errgroup.WithContext(ctx) が必要です。
- Group.Go のシグネチャは依然として func() errorcontext.Context を受け取らない)です。

  • errgroup.WithContext が返す 子コンテキスト (ctx) は、どの goroutine でもキャンセルやタイムアウトを共有できる点が便利です。
  • 今後のバージョンでシグネチャ変更があればリリースノートに明示されますので、常に公式ドキュメント(https://pkg.go.dev/golang.org/x/sync/errgroup)を参照してください。

2. デッドロック・リーク回避チェックリスト

項目 確認ポイント 推奨ツール
Mutex の取得順序 複数の Lock が同一順序で呼ばれているか 静的解析 (go vet -run=atomic)
channel の対称性 送信側と受信側が必ず対になるか(バッファサイズ・クローズ) staticcheck
goroutine の終了パス 全ての goroutine が ctx.Done() または wg.Done() に到達するか カスタムテスト (TestLeak)
タイムアウト設定 長時間ブロックしうる操作に context.WithTimeout を使用しているか コードレビュー
errgroup/WaitGroup のカウント漏れ AddDone が 1:1 になるか -race オプションで実行

3. 実務向けサンプルコードの取得

リポジトリには以下が同梱されています。

ディレクトリ 内容
example/workerpool Worker Pool の実装とベンチマーク
example/pipeline 3 ステージ Pipeline とテスト
example/fanoutin Fan‑out / Fan‑in パターン
example/errgroup 正しい errgroup.WithContext 使用例

4. まとめのベストプラクティス

  1. 設計は並行性で考える → タスク分割・データフローを明確化。
  2. 実装は標準ライブラリだけで完結goroutine, channel, select, sync, context, errgroup を組み合わせる。
  3. リソース制御はコンテキストと WaitGroup で一元管理 → キャンセル・タイムアウトが漏れないようにする。
  4. テストとベンチマークは必須go test -race, -bench でデッドロックやリークを早期検出。
  5. 公式ドキュメントとリリースノートを定期的にチェック → API 変更(例: errgroup のシグネチャ)への対応が楽になる。

参考リンク


以上が Go 1.22 に合わせて改訂した並行処理入門と実務パターンです。ぜひローカル環境でサンプルを動かし、実際のプロジェクトへ応用してみてください。

スポンサードリンク

お得なお知らせ

スポンサードリンク
AI時代のキャリア構築

プログラミング学習、今日から動き出す

「何から始めるか」で止まっている人こそ、無料説明会や本で自分に合うルートを30分で確定できます。

Enjoy Tech!|月額制でWeb系に強い▶ (Kindle本)ITエンジニアの転職学|後悔しないキャリア戦略▶

▶ AIコーディング環境なら  実践Claude Code入門(Amazon)が実務で即使える入門書です。Amazonベストセラーにも選ばれていますよ。


-Go言語