本文へスキップ
BecomeCoder

Goコース · 第6章 並行処理 · レッスン22

channel ― goroutine 間で値を受け渡す

ブラウザで完結

導入

別々に走る goroutine の間で、安全に値をやり取りする通り道が channel(チャネル) です。「メモリを共有して通信するな、通信してメモリを共有せよ」が Go の合言葉です。

説明

package main

import "fmt"

func main() {
    ch := make(chan string) // string を運ぶチャネルを作る

    go func() {
        ch <- "計算おわり" // チャネルに値を送る
    }()

    msg := <-ch // チャネルから値を受け取る(届くまで待つ)
    fmt.Println(msg)
}
  • make(chan string) … string を受け渡すチャネルを作ります。
  • ch <- "..." … チャネルに値を 送る(矢印がチャネルへ向く)。
  • <-ch … チャネルから値を 受け取る(矢印がチャネルから出る)。
  • 受け取り側は、値が届くまで自動的に待ちます。この「待ち合わせ」が同期の役割を果たします。

前レッスンの time.Sleep で待つ代わりに、チャネルの受信で「処理が終わるまで待つ」を正確に表現できます。

やってみよう

go func() { ch <- "..." }() は、その場で無名関数を goroutine として起動する書き方です。msg := <-ch が「値が届くまで待つ」おかげで、Sleep なしでも結果を取りこぼしません。

演習

goroutine から2つの値を順に送り、1つ目 2つ目 の順で受け取って表示してください。

ヒント1を見る

送る側で ch <- "1つ目" の下に ch <- "2つ目" を足し、受け取る側でも2回受け取ります。

ヒント2を見る

受け取りは fmt.Println(<-ch) を2行並べれば十分です。バッファなしチャネルは「受け取る人が来るまで送る側が待つ」ので、順番は入れ替わりません。

実際に動かしてみよう

下のエディタにGoを書いて「実行」を押すと、学習用シミュレータが fmt の出力を表示します(本物のGoコンパイラではなく、教材の範囲を再現した軽量エンジンです)。スライス・マップ・構造体・インターフェース・goroutine/channel なども動きます。本文の例を書き換えて動かしてみましょう(並行処理の実行順は決定的に再現しているため、本物のインターリーブとは異なる場合があります)。

Go — ブラウザ内で実行(学習用シミュレータ)

Goの教材サブセットを動かす学習用シミュレータを読み込みます(本物のGoコンパイラではなく、動きを再現した軽量な自作エンジンです)。
スクロールして表示された時点でも自動で読み込まれます。

次のレッスンへ →