ホーム プログラミング言語 golang go concurrent Go 言語の同時印刷 (チャネルによって実装)

Go 言語の同時印刷 (チャネルによって実装)

 
 
前の例では、バッファーなしのチャネルを作成しました。バッファリングされていないチャネルを使用してデータをロードする場合、別のゴルーチンで別のチャネルがフェッチされるまでローダーはブロックされます。同様に、チャネルにデータが入力されていない場合、受信機はチャネルからデータを取得しようとするときにもブロックされます。送信操作と受信操作は同期して行われます。

 

goroutine とチャネルを組み合わせて、同時印刷の例を通してその使用法を示してみましょう。

package main

import (
    "fmt"
)

func printer(c chan int) {

    //データが届くまで無限ループ開始
    for {

        // チャネルからデータを取得する
        data := <-c

        //0が送信されたら処理終了
        if data == 0 {
            break
        }

        // データを表示する
        fmt.Println(data)
    }

    // mainに処理が終わったことを通知(OK!)
    c <- 0

}

func main() {

    // チャネル作成
    c := make(chan int)

    //printerをgoで実行し、チャネルを渡す
    go printer(c)

    for i := 1; i <= 10; i++ {

        // データをprinterに渡す
        c <- i
    }

    //printerにデータが無くなったことを通知
    c <- 0

    //printerの処理が終わるまで待つ(OKだよ!)
    <-c

} 

コードを実行すると、出力は次のようになります。

1
2
3
4
5
6
7
8
9
10

コードの説明は次のとおりです。

  • 10行目は無限ループを作成し、16行目で取得したデータが0の場合のみループを抜けます。
  • 13 行目では、関数パラメータによって渡されたチャネルから整数値が取得されます。
  • 行 21、整数値を出力します。
  • 25 行目で、ループを終了するときに、チャネルを通じて main() 関数に作業が完了したことが通知されます。
  • 32 行目は、ゴルーチン間通信用の整数チャネルを作成します。
  • 35行目ではprinter()関数を並行して実行するゴルーチンを作成しています。
  • 37 行目、数値サイクルを構築し、チャネルを通じてプリンターによって構築されたゴルーチンに 1 から 10 までの数値を送信します。
  • 44 行目では、チャネルに 0 が渡され、前のデータ処理が完了した後にループが終了することを示します。
  • 47 行目では、データが送信された後、同時実行性とスケジュールの理由により、タスクが同時に実行されます。ここでは、main() を終了する前に、プリンターの 25 行目がデータを返すのを待つ必要があります。

この例の設計パターンは、典型的な生産者と消費者です。プロデューサは 37 行目のループで、コンシューマは printer() 関数です。例全体では 2 つのゴルーチンを使用しています。1 つは main() で、もう 1 つは 35 行目の printer() 関数によって作成されたゴルーチンです。 2 つのゴルーチンは、32 行目で作成されたチャネルを通じて通信します。このチャネルには以下の 2 つの機能があります。

  • データ転送: 40 行目でデータを送信し、13 行目でデータを受信します。
  • 制御命令:セマフォに似た機能。ゴルーチンの動作を同期します。関数は次のように簡単に説明されます。
    • 44行目:「データがありません!」
    • 25行目:「分かった!」
    • 47行目:「電話してください!」
 

「 Go 言語の同時印刷 (チャネルによって実装)」についてわかりやすく解説!絶対に観るべきベスト2動画

Go言語とは?|プログラミング言語のGo言語について3分でわかりやすく解説します【プログラミング初心者向け】
【初心者必見!】Go言語とは?できることや学ぶメリット・将来性について解説