time.After是一个非常实用的函数,它返回一个用于读取的单向通道(<-chan time.Time),这个通道会在指定的时间间隔之后发送当前时间。这个机制常被用于实现超时控制、延迟执行等场景。
应用场景:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
package main
import ( "fmt" "time" )
func main() { // 等待3秒 timer := time.After(3 * time.Second)
// 阻塞等待time.After的通道发送时间 x := <-timer fmt.Println(x) // 当上面的<-timer执行后,说明已经等待了5秒 fmt.Println("3秒已过")
// 你可以继续执行你的逻辑... } |
time.After还常用于实现超时控制。比如,你可能在发送一个HTTP请求时,不希望这个请求无限制地等待响应,而是想在某个超时时间后停止等待并处理超时逻辑:
超时控制应该是非常常见的使用场景。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
package main
import ( "fmt" "io/ioutil" "net/http" "time" )
func main() { client := &http.Client{ Timeout: 10 * time.Second, // 设置客户端超时时间 }
// 模拟一个可能会超时的请求 resp, err := client.Get("http://example.com/may-timeout") if err != nil { fmt.Println("请求错误:", err) return } defer resp.Body.Close()
// 使用time.After实现读取响应体的超时 done := make(chan bool, 1) go func() { // 模拟读取响应体,实际中可能是ioutil.ReadAll(resp.Body) // 这里用time.Sleep模拟耗时操作 time.Sleep(2 * time.Second) done <- true }()
select { case <-done: // 读取成功 body, _ := ioutil.ReadAll(resp.Body) fmt.Println("读取响应体成功:", string(body)) case <-time.After(1 * time.Second): // 超时 fmt.Println("读取响应体超时") } } |
超时控制channel结合了select。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
package main
import ( "fmt" "time" )
// 定义 stop 函数,接受 deviceid 和 gunid 作为参数 func stop(deviceid int, gunid int) { fmt.Printf("Stopping with device ID: %d and gun ID: %d\n", deviceid, gunid) }
func main() { // 设定要传递给 stop 函数的参数 deviceid := 1 gunid := 2
// 使用 goroutine 异步执行计时器 go func() { // 创建一个通道,将在 10 秒后关闭 timer := time.After(10 * time.Second)
// 等待通道关闭,即等待 10 秒 <-timer
// 在 10 秒后执行 stop 函数 stop(deviceid, gunid) }()
// 主程序可以继续执行其他任务 fmt.Println("Main program continues to run...")
// 为了演示,让主程序运行一段时间,以便观察 stop 函数的执行 time.Sleep(15 * time.Second) fmt.Println("Main program ends.") } |
time.Sleep和time.After什么区别?