欢迎访问
我们一直在努力

golang设定最长执行时间的几种方法

前言

web服务开发过程中经常遇到我们需要某一个逻辑最长执行多少时间,超过这个时间需要快速返回而不是继续等待,常用的有这么几种方法

方法一

ch := make(chan bool, 1)
timeout := make(chan bool, 1)

// Send a message to our timeout channel after 1s
go func() {
  time.Sleep(1 * time.Second)
  timeout <- true
}()

go func() {
  // do something
  ch <- true
}()

// Wait for a message, or timeout
select {
case <-ch:
  fmt.Println("Read from ch")
case <-timeout:
  fmt.Println("Timed out")
}

一句话评价为快速但是资源有浪费,这是最容易想到的方法,但是不足之处在于第一个协程总是需要等待1s,即使我们需要的处理很快就完成,有一定的资源浪费,而且资源没有回收,都需要等待gc。

方法二

ch := make(chan bool, 1)

go func() {
  // do something
  ch <- true
  close(ch)
}()

select {
case <-ch:
  fmt.Println("Read from ch")
case <-time.After(1 * time.Second):
  fmt.Println("Timed out")
}

在方法一的基础上优化了一些,提前close了ch,这样如果处理很快完成,ch也很块被释放,但是定时器好像还是仍然需要等1s后才可以交给gc去释放。

方法三

ch := make(chan bool, 1)

go func() {
  ch <- true
  close(ch)
}()

timer := time.NewTimer(1 * time.Second)
defer timer.Stop()

select {
case <-ch:
  fmt.Println("Read from ch")
case <-timer.C:
  fmt.Println("Timed out")
}

在方法二的基础上继续优化,定时器修改为可以提前终止的方式,这样我们是主动的去释放掉所有临时的资源了,因此推荐这种方法。

综述

最终完整代码见这个,以接口的方式提供。

var ErrTimeout = errors.New("timeout")

func RunWithTimeout(handler func(), timeout time.Duration) error {
    done := make(chan bool, 1)
    go func() {
        handler()
        done <- true
        close(done)
    }()

    timer := time.NewTimer(timeout)
    defer timer.Stop()
    select {
    case <-timer.C:
        return ErrTimeout
    case <-done:
        return nil
    }
}
未经允许不得转载:威威牛 » golang设定最长执行时间的几种方法
分享到: 更多 (0)