Tag: timeout

1 Posts

thumbnail
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 } }