方式1
第一个技巧的源码保存在 timeOut1.go
中,并分为四部分介绍。
timeOut1.go
的第一部分显示如下代码:
package main
import (
"fmt"
"time"
)
timeOut1.go
第二段代码如下:
func main() {
c1 := make(chan string)
go func () {
time.Sleep(time.Second * 3)
c <- "c1 OK"
}()
time.Sleep()
调用用于模拟函数完成其工作通常需要的时间。在这个例子里,匿名函数以 goroutine 方式执行,它将在大约 3 秒(time.Second * 3
)后写消息到 c1
channel。
timeOut1.go
的第三段包含如下代码:
select {
case res := <- c1:
fmt.Println(res)
case <- time.After(time.Second * 1):
fmt.Println("timeout c1")
}
time.After()
函数调用的目地是等待指定时间。这个例子中,您不用关心 time.After()
返回的实际值,但实际上 time.After()
函数调用介绍意味着超时了。例子中由于 time.After()
函数指定的值小于上节以 goroutine 方式执行的 time.Sleep()
调用中使用的值,您极有可能得到一个超时信息。
timeOut1.go
的其余代码如下:
c2 := make(chan string)
go func() {
time.Sleep(3 * time.Second)
c2 <- "c2 OK"
}()
select {
case res := <-c2:
fmt.Println(res)
case <- time.After(4 * time.Second):
fmt.Println("timeout c2")
}
}
上面这段代码执行一个 goroutine 并使用 time.After(4 * time.Second)
定义了一个 4 秒的超时期限,由于 time.Sleep()
的调用,这个goroutine 将执行大约 3 秒。如果 time.After(4 * time.Second)
调用的返回在您从 select
块的第一个分支里的 c2 channel 获得值之后,那么就不会超时;否则,将超时!然而,在这个例子中,time.After()
调用的值提供了足够的时间对于 time.Sleep()
调用的返回,因此您极可能不会得到一个超时信息。
执行 timeOut1.go
产生如下输出:
$go run timeOut1.go
timeout c1
c2 OK
正如期望的,第一个 goroutine 没有完成它的工作,而第二个有足够的时间去完成。