非常に時間のかかる処理をゴルーチンにするといつまでも終わらなくなる可能性がある。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つしか終わらなかった。