タイムアウト

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