チャネルはゴルーチンの間で通信するためのデータだ。次のように生成する。
ch := make(chan T, bufsize)
T はチャネルでやり取りするデータの型、bufsize はデータを格納するバッファのサイズで省略すると 0 になる。チャネルの型は chan T。
関数の引数や変数の型指定の時、chan の前に <- をつけると受信専用に、後に <- をつけると送信専用になる。 チャネルを使うと、ゴルーチンの終了待ちができるようになる。 次の例では test 関数をゴルーチンとして呼び出し、チャネルを渡している。test 関数は 0.5 秒間隔で name を出力し、終了するときにチャネルを通じて name を送ってくる。main 関数ではチャネルからデータが送られてくるのを待っている。
package main import ( "fmt" "time" ) func test(n int, name string, c chan<- string) { for i := 1; i <= n; i++ { fmt.Println(i, name) time.Sleep(500 * time.Millisecond) } c <- name } func main() { c := make(chan string) go test(6, "foo", c) go test(4, "bar", c) go test(8, "baz", c) for i := 0; i < 3; i++ { name := <- c fmt.Println(name) } }
実行してみよう。
^o^ > go run go_channel.go 1 foo 1 baz 1 bar 2 foo 2 baz 2 bar 3 foo 3 baz 3 bar 4 foo 4 baz 4 bar 5 foo 5 baz bar 6 foo 6 baz foo 7 baz 8 baz baz
数字とともに出力されているのが test 関数内で出力したもの、数字のないのがゴルーチンが終了した後に main 関数で出力したものだ。3つのゴルーチンが並行して動き、main 関数ではその終了を待っていることがわかる。