導入
別々に走る 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行並べれば十分です。バッファなしチャネルは「受け取る人が来るまで送る側が待つ」ので、順番は入れ替わりません。