非常に時間のかかる処理をゴルーチンにするといつまでも終わらなくなる可能性がある。select
と time
パッケージの After
を組み合わせると、タイムアウトの処理ができる。
After
は一定時間が経過したらデータを送信するチャネルを返す。なので、select
と併用することでタイムアウトの処理ができるわけだ。
package main import ( "fmt" "time" ) func fibo(n int) int { if n < 2 { return 1 } else { return fibo(n - 2) + fibo(n - 1) } } func main() { ch := make(chan int, 5) for _, n := range []int{ 41, 40, 38, 36, 34 } { go func(x int) { ch <- fibo(x) }(n) } for i := 5; i > 0; { select { case n := <- ch: fmt.Println(n) i-- case <- time.After(500 * time.Millisecond): fmt.Println("Timeout") i = 0 } } }
ここでは、時間のかかる処理(関数)として、フィボナッチ数を求める関数を用意した。これで5つのゴルーチンを起動しておき、その終了を待つと同時に time.After
で500ミリ秒でタイムアウトするようにしている。つまり time.After
の返り値であるチャネルからデータが送られてくる前に処理が終わったゴルーチンだけが結果を表示するわけだ。
^o^ > go run channel_after.go 9227465 24157817 63245986 Timeout
このとおり、500ミリ秒では3つしか終わらなかった。