Golang time after

Golang time after使用

golang 中,谁也无法保证某些情况下的 select 是否会永久阻塞。很多时候都需要设置一下 select 的超时时间,可以借助 time 包的 After() 实现。

Golang time after详解

语法

func After(d Duration) <-chan Time

时长

参数 描述
d 时长

说明

After() 函数接受一个时长 d,然后它 After() 等待 d 时长,等待时间到后,将等待完成时所处时间点写入到 channel 中并返回这个只读 channel。

所以,将该函数赋值给一个变量时,这个变量是一个只读 channel,而 channel 是一个指针类型的数据,所以它是一个指针。

Golang time after典型用法

time after触发

package main import ( "fmt" "time" ) func main() { fmt.Println("嗨客网(www.haicoder.net)") fmt.Println("Start Time =", time.Now()) a := time.After(5*time.Second) fmt.Println(<-a) fmt.Println("End Start Time =", time.Now()) }

程序运行后,输出如下图所示:

42_Go语言time After使用.png

我们看到,time After 在等待了 5 秒之后,返回了一个只读的 channel。因此,如果将 After() 放进 select 语句块的一个 case 中,那么就可以让其它的 case 有一定的时间长度来监听读、写事件。

如果在这段时长内其它 case 还没有有可读、可写事件,这个 After() 所在 case 就会结束当前的 select,然后终止 select (如果 select 未在循环中)或进入下一轮 select (如果 select 在循环中)。

time after设置超时

package main import ( "fmt" "time" ) func main() { fmt.Println("嗨客网(www.haicoder.net)") ch1 := make(chan string) // 激活一个goroutine,但5秒之后才发送数据 go func() { time.Sleep(5 * time.Second) ch1 <- "put value into ch1" }() select { case val := <-ch1: fmt.Println("recv value from ch1:",val) return // 只等待3秒,然后就结束 case <-time.After(3 * time.Second): fmt.Println("3 second over, timeover") } }

程序运行后,输出如下图所示:

43_Go语言time After使用.png

上面出现了超时现象,因为新激活的 goroutine 首先要等待 5 秒,然后才将数据发送到 channel ch1 中。但是 main goroutine 继续运行到 select 语句块,由于第一个 case 未满足条件(注意,main goroutine 并不会因此而阻塞)。

评估第二个 case 时,将执行 time.After() 等待 3 秒,3 秒之后读取到该函数返回的通道数据,于是该 case 满足 select 的条件,该 select 因为没有在循环中,所以直接结束,main goroutine 也因此而终止。自始至终,新激活的 goroutine都没有机会将数据发送到 ch1 中。

Golang time after使用总结

在 golang 中,谁也无法保证某些情况下的 select 是否会永久阻塞。很多时候都需要设置一下 select 的超时时间,可以借助 time 包的 After() 实现。