方式2

    timeOut2.go 的第一部分如下:

    timeOut2.go 的第二段代码如下:

    1. func timeout(w *sync.WaitGroup, t time.Duration) bool {
    2. temp := make(chan int)
    3. go func() {
    4. time.Sleep(5 * time.Second)
    5. defer close(temp)
    6. w.Wait()
    7. }()
    8. case <-temp:
    9. return false
    10. case <-time.After(t):
    11. return true
    12. }
    13. }

    上面的代码里,time.After() 调用使用的时间周期是 timeout() 函数的一个参数,就是说它可变。再次, 块实现了超时逻辑。另外,w.Wait() 调用使 timeout() 函数无期限的等待一个匹配的 sync.Done() 函数来结束。当 w.Wait() 调用返回,select 表达式的第一个分支就会执行。

    timeOut2.go 的第四部分如下:

    1. duration := time.Duration(int32(t)) * time.Millisecond
    2. fmt.Printf("Timeout period is %s\n", duration)
    3. if timeout(&w, duration) {
    4. fmt.Println("Timed out!")
    5. } else {
    6. fmt.Println("OK!")
    7. }

    time.Duration() 函数转换一个整数值给一个之后使用到的 time.Duration 变量。

    timeOut2.go 的其余代码如下:

    执行 timeOut2.go 产生如下输出:

    1. $go run timeOut2.go 10000
    2. Timeout period is 10s
    3. Timed out!

    执行 timeOut2.go 的超时周期比匿名 goroutine 的 time.Sleep(5 * time.Second) 长。然而,没有必要的 w.Done() 调用,匿名 goroutine 不能返回因为 time.After() 调用先结束了,所以第一个 if 表达式的 timeout() 函数返回 true。第二个 if 表达式,匿名函数不必等待,因为 time.Sleep(5 * time.Second) 将先于 time.After(t) 结束,所以 timeout() 函数返回 false:

    然而,第二次执行,这个超时周期太短了,所以这两个 的执行都没有足够的时间完成,因此都超时了。