チャネルとゴルーチンの終了待ち
チャネルはゴルーチンの間で通信するためのデータだ。次のように生成する。
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 関数ではその終了を待っていることがわかる。
