Go Academy · レッスン

ファンインとファンアウトのパターン

複数のチャネルの統合と処理の分配

レッスン 3/413 ステップ

「ファンインとファンアウトのパターン」はCoddyKit上の無料Go Academyレッスンです。 これはレッスン3/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはGo Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 Go Academyコースには全4レッスンが含まれています。

ファンアウトとは何か

ファンアウトは、1つのチャネルから複数のゴルーチンに処理を分配し、並列処理を可能にします。各ワーカーは同じ入力チャネルから受信します。

ファンアウトの例

共有された jobs チャネルから全員が読み取る N 個のワーカーを起動します:

func fanOut(jobs <-chan Job, n int) {
    for i := 0; i < n; i++ {
        go func() {
            for job := range jobs {
                process(job)
            }
        }()
    }
}

ファンインとは何か

ファンインは複数のチャネルを1つに統合するため、1つのコンシューマーが複数のプロデューサーから結果を読み取れます。

ゴルーチンによるファンイン

入力チャネルごとにゴルーチンを1つ起動し、各ゴルーチンが共有出力チャネルへ値を転送します。

func fanIn(cs ...<-chan int) <-chan int {
    out := make(chan int)
    var wg sync.WaitGroup
    for _, c := range cs {
        wg.Add(1)
        go func(ch <-chan int) {
            defer wg.Done()
            for v := range ch { out <- v }
        }(c)
    }
    go func() { wg.Wait(); close(out) }()
    return out
}

selectによるファンイン

入力チャネルの数が固定されている場合は、チャネルごとにゴルーチンを起動するよりも select ループのほうが簡単です。

func merge(a, b <-chan int) <-chan int {
    out := make(chan int)
    go func() {
        defer close(out)
        for a != nil || b != nil {
            select {
            case v, ok := <-a: if !ok { a = nil } else { out <- v }
            case v, ok := <-b: if !ok { b = nil } else { out <- v }
            }
        }
    }()
    return out
}

パイプラインステージ

ファンアウトとファンインを組み合わせると、1つの入力チャネル、N 個の並列ワーカー、1つの統合出力チャネルからなるパイプラインステージを構築できます。

func parallelStage(in <-chan Work, n int) <-chan Result {
    outs := make([]<-chan Result, n)
    for i := 0; i < n; i++ {
        outs[i] = worker(in)
    }
    return fanIn(outs...)
}

チャネルを正常に閉じる

チャネルを閉じるのは送信側です。受信側は2値形式の受信、または range によってチャネルの終了を検出します。受信側からチャネルを閉じてはいけません。

for v := range in { // exits when in is closed
    process(v)
}

WaitGroupによる調整

sync.WaitGroup を使用して、ファンアウトのすべてのワーカーが完了したことを確認します。その後、出力チャネルを閉じて、下流のコンシューマーが処理を終了できるようにします。

バックプレッシャー

パイプラインステージ間にバッファ付きチャネルを使用して、バーストを吸収します。バッファサイズは、プロデューサーとコンシューマーの想定レイテンシ差に基づいて決めます。

out := make(chan Result, 100) // buffer absorbs bursts

エラーの伝播

値とエラーの両方を保持する構造体で結果をラップします。これにより、パニックを発生させずに、データとともにエラーをパイプライン内に流せます。

type Result struct {
    Value int
    Err   error
}

コンテキストによるキャンセル

パイプラインの各ステージにコンテキストを渡し、各ステージで ctx.Done() を確認します。キャンセルされたときにパイプライン全体を停止できます。

case <-ctx.Done():
    return ctx.Err()

確認問題

ファンインパターンでは、統合された出力チャネルを閉じるのは何ですか?

復習: ファンインとファンアウト

重要なポイント:

  • ファンアウト: 複数のワーカーが1つのチャネルから読み取ります
  • ファンイン: ソースごとに1つのゴルーチンを起動し、1つの出力チャネルに統合します
  • WaitGroup が統合されたチャネルのクローズを調整します
  • キャンセルにはコンテキストを、バックプレッシャーにはバッファ付きチャネルを使用します
無料で開始

AI チューターと学ぶ Go — 無料

ブラウザでリアルコードを書いて実行し、24/7 の AI チューターから瞬時にサポートを受け、ウェブまたはアプリで続きから学習できます。

コース
51
レッスン
203

よくある質問

「ファンインとファンアウトのパターン」レッスンは無料ですか?

はい。「ファンインとファンアウトのパターン」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、Go Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 Go Academyコースには全4レッスンが含まれています。

「ファンインとファンアウトのパターン」で何を学びますか?

複数のチャネルの統合と処理の分配 ブラウザで直接実行するハンズオンコードでGo Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。

Go Academyを始めるのに経験は必要ですか?

事前経験は必要ありません。CoddyKitのGo Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン3/4です。

「ファンインとファンアウトのパターン」レッスンにはどのくらい時間がかかりますか?

ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。

このGo Academyレッスンでコードを書いて実行できますか?

はい。すべてのGo Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。

このコースのすべてのレッスン

  1. select文
  2. タイムアウトとTicker
  3. ファンインとファンアウトのパターン
  4. ワーカープールパターン
← Go Academyに戻る