カテゴリ: Go言語 更新日: 2025/12/30

Go言語の並行処理設計パターン集!パイプライン・ファンアウト徹底解説

Go言語の並行処理設計パターン集(パイプライン・ファンアウトなど)
Go言語の並行処理設計パターン集(パイプライン・ファンアウトなど)

先生と生徒の会話形式で理解しよう

生徒

「Goで複数の処理を同時に動かすとき、どうやって設計すればいいですか?」

先生

「Goでは、goroutineとchannelを組み合わせて効率的に処理を設計する方法があります。代表的なのはパイプラインとファンアウトのパターンです。」

生徒

「パイプラインとファンアウトって何ですか?」

先生

「簡単に言うと、パイプラインは処理を順番につなげる流れ、ファンアウトは同じ処理を複数のgoroutineで分担するやり方です。」

1. パイプラインパターンとは?

1. パイプラインパターンとは?
1. パイプラインパターンとは?

パイプラインは、処理を段階ごとに分けて、それぞれを独立したgoroutineで実行し、channelでデータを渡す設計パターンです。これにより、大きな処理を小さく分けて効率よく処理できます。

例えば、データを読み込む、加工する、出力するという三段階の処理を考えます。各段階を別のgoroutineで実行し、channelでデータを渡すことで、処理全体の速度を向上させられます。

2. パイプラインのサンプルコード

2. パイプラインのサンプルコード
2. パイプラインのサンプルコード

package main

import "fmt"

func main() {
    nums := make(chan int)
    squares := make(chan int)

    // 数字を生成するgoroutine
    go func() {
        for i := 1; i <= 5; i++ {
            nums <- i
        }
        close(nums)
    }()

    // 数字を二乗するgoroutine
    go func() {
        for n := range nums {
            squares <- n * n
        }
        close(squares)
    }()

    // 結果を表示
    for sq := range squares {
        fmt.Println(sq)
    }
}

この例では、数字を生成するgoroutineと二乗するgoroutineがchannelでデータを渡しています。これがパイプラインの基本的な考え方です。

3. ファンアウトパターンとは?

3. ファンアウトパターンとは?
3. ファンアウトパターンとは?

ファンアウトは、同じ入力を複数のgoroutineで処理して負荷を分散する設計パターンです。大量の処理を効率よくさばくときに有効です。

例えば、ウェブから複数のデータを取得して処理する場合、goroutineを複数立ち上げて同時に処理することで、全体の処理時間を短縮できます。

4. ファンアウトのサンプルコード

4. ファンアウトのサンプルコード
4. ファンアウトのサンプルコード

package main

import (
    "fmt"
    "sync"
)

func worker(id int, jobs <-chan int, results chan<- int, wg *sync.WaitGroup) {
    defer wg.Done()
    for j := range jobs {
        results <- j * 2
    }
}

func main() {
    jobs := make(chan int, 5)
    results := make(chan int, 5)
    var wg sync.WaitGroup

    // ワーカーを3つ立ち上げる
    for w := 1; w <= 3; w++ {
        wg.Add(1)
        go worker(w, jobs, results, &wg)
    }

    // ジョブを送る
    for j := 1; j <= 5; j++ {
        jobs <- j
    }
    close(jobs)

    // ワーカーの終了を待つ
    go func() {
        wg.Wait()
        close(results)
    }()

    for res := range results {
        fmt.Println(res)
    }
}

この例では、3つのワーカーgoroutineがjobsチャネルからデータを受け取り、処理結果をresultsチャネルに送っています。これがファンアウトの基本形です。

5. パイプラインとファンアウトを組み合わせる

5. パイプラインとファンアウトを組み合わせる
5. パイプラインとファンアウトを組み合わせる

実際のシステムでは、パイプラインとファンアウトを組み合わせることで、高速かつ効率的な並行処理が可能です。パイプラインで段階的に処理しつつ、各段階でファンアウトを使い処理を分散させることで、大量データの処理もスムーズになります。

ポイントは、goroutineを無制限に増やさず、channelで適切にデータを制御することです。バッファ付きchannelを利用すると、処理が詰まるのを防ぎ、安定した並行処理ができます。

カテゴリの一覧へ
新着記事
New1
Go言語
Go言語のオブジェクト指向の特徴を完全ガイド!初心者でも理解できる他言語との違い
New2
Go言語
Go言語の条件分岐の見やすい書き方を徹底解説!初心者でもわかるif文の使い方
New3
Kotlin
Kotlinのクラス設計に役立つベストプラクティスまとめ|初心者でもわかるクラス設計の考え方
New4
Kotlin
Kotlinでアーキテクチャ設計の基本!MVC・MVP・MVVMの違いを解説
人気記事
No.1
Java&Spring記事人気No1
Go言語
Go言語の関数パラメータ!値渡しと参照渡しの違いを理解しよう
No.2
Java&Spring記事人気No2
Swift
Swift Playgroundの使い方を完全解説!初心者に最適な学習環境の始め方
No.3
Java&Spring記事人気No3
Swift
Swift開発環境の構築方法を徹底解説!Xcode・Windows・Linux対応
No.4
Java&Spring記事人気No4
Kotlin
Gradleファイル(build.gradle.kts)の書き方と役割をやさしく解説!Kotlin初心者向け完全ガイド
No.5
Java&Spring記事人気No5
Kotlin
Kotlinのインストール方法まとめ!Windows・Mac・Linux別にステップ解説
No.6
Java&Spring記事人気No6
Go言語
Go言語のWebアプリにおけるセキュリティベストプラクティス集
No.7
Java&Spring記事人気No7
Kotlin
Kotlinの演算子一覧と使い方!算術・比較・論理演算子の基本を解説
No.8
Java&Spring記事人気No8
Kotlin
Android Studioのインストール手順と初期設定を初心者向けに完全解説!