如何在Go语言中使用超时


当我们不想等待某些goroutine(花费的时间超过预期)的输出时,超时起着重要的作用。需要注意的是,Go本身并不直接支持超时,但我们可以很容易地实现它。

假设我们需要从一个通道ch接收一些值,但我们不想等待超过3秒钟来接收值。如果3秒后我们才收到输出,那么我们希望丢弃它并打印不同的消息,而不是等待更长时间的输出。

示例1

让我们首先探讨一个简单的案例,其中我们从一个函数中获得输出需要较长时间。

请看下面的代码。

package main

import (
   "fmt"
   "time"
)

func timeConsuming() string {
   time.Sleep(5 * time.Second)
   return "The timeConsuming() function has stopped"
}

func main() {
   currentChannel := make(chan string, 1)

   go func() {
      text := timeConsuming()
      currentChannel <- text
   }()

   select {
   case res := <-currentChannel:
      fmt.Println(res)
   }
   fmt.Println("Main function exited!")
}

在上面的代码中,我们有一个名为timeConsuming()的函数,它表示一个可能在较长时间或所需时间后返回特定值的函数。一个例子是网络请求,其中获取数据花费的时间太长,用户感到沮丧。

在上面代码的main函数中,我们有一个带缓冲区的通道,然后我们使用select语句等待数据的到来。因此,在上述情况下,整个代码必须等到函数timeConsuming()完成工作。

输出

如果我们使用命令go run main.go运行上面的代码,我们将得到以下输出。

The timeConsuming() function has stopped
Main function exited!

示例2

现在,假设我们不想等待函数timeConsuming()完成其执行。在这种情况下,我们可以使用time包的After()函数。

语法

After()函数的语法是:

func After(d Duration) −- chan Time

After函数等待d持续时间结束后,它将返回一个通道上的当前时间。

请看下面的代码,我们使用After函数来注册超时。

package main

import (
   "fmt"
   "time"
)

func timeConsuming() string {
   time.Sleep(5 * time.Second)
   return "The timeConsuming() function has stopped"
}

func main() {
   currentChannel := make(chan string, 1)

   go func() {
      text := timeConsuming()
      currentChannel <- text
   }()

   select {
   case res := <-currentChannel:
      fmt.Println(res)
   case <-time.After(3 * time.Second):
      fmt.Println("Out of time :(")
   }
   fmt.Println("Main function exited!")
}

输出

如果我们使用命令go run main.go运行上面的代码,我们将得到以下输出。

Out of time :(
Main function exited!

更新于:2021年11月1日

3K+ 次浏览

启动你的职业生涯

通过完成课程获得认证

开始学习
广告