#### 在群里讨论怎么限制某函数的执行时间,想了很久,终于找到非常简洁的写法(手动捂脸,很快被打脸),之所以在这里发表,是因为我见过太多新手写不是很好! 也许是许久没发文章,就闲来蛋疼发篇文章,但是这篇文章并不是讲如何限制函数的执行时间,因为函数一旦执行则无法中断,所以不存在这种情况,那么下面讨论的则是:某某函数执行超时后的触发器(注意不是函数开始执行超时)
#### 废话不多说,直接呈上2种我个人认为比较好的写法
### (1)第1种是我目前能想到比较好且耗时时间很稳定的写法,但是不易懂且稍微多点内存,代码如下:
```
package main
import (
"fmt"
"time"
)
var start time.Time
var end time.Time
func main() {
test := func() {
start=time.Now()
time.Sleep(5e9)
}
limitTime1(test, 3e9)//可以将这里的时间改为超过5s
end=time.Now()
fmt.Println("test()耗时:",end.Sub(start))
}
func limitTime1(test func(), duration time.Duration) {
var ch = make(chan bool)
go func() {
go func() {
//先开启计时
<-time.NewTimer(duration).C
//如果能执行到这里则说明test()函数超时
ch<-true
}()
//再执行要监控的程序
test()
//如果能执行到这里则说明test()函数正常执行完,不超时
ch <- true
}()
//这里阻塞等于模拟了监控计时
<-ch
}
```
### 结果截图如下:
![image.png](https://static.studygolang.com/191226/33c5b86e1286b98ce2da8e32e75120a2.png)
### (2)第2种是我认为不够简洁而且耗时时间由于随机性可能会出现误差比较大(可能2个数量级)的写法,但是易懂点,代码如下:
```
package main
import (
"fmt"
"time"
)
var start time.Time
var end time.Time
func main() {
test := func() {
start=time.Now()
time.Sleep(5e9)
}
limitTime(test, 3e9)//可以将这里的时间改为超过5s
end=time.Now()
fmt.Println("test()耗时:",end.Sub(start))
}
func limitTime(test func(), duration time.Duration) {
ch := make(chan bool)
var t <-chan time.Time
go func() {
//开始计时
t = time.NewTimer(duration).C
ch <- true
//运行监控程序
test()
ch <- true
}()
//阻塞到t被赋值
<-ch
//开启监控,在这里会被阻塞
select {
case <-t:
case <-ch:
}
}
```
### 结果截图如下:
![image.png](https://static.studygolang.com/191226/d8d93449ed33fa599b651f8ba76bc82d.png)
### (3)下面放上大佬的写法,简直吊打我上面的2种,写出了go范,我实在惭愧~~~~,大佬的源码是:[https://github.com/geektime-geekbang/go_learning/blob/master/code/ch47/optimization_test.go](https://github.com/geektime-geekbang/go_learning/blob/master/code/ch47/optimization_test.go),我改了下大佬的代码如下:
```
package main
import (
"fmt"
"time"
)
func AsyncService(service func() string) chan string {
retCh := make(chan string, 1)
go func() {
ret := service()
fmt.Println("service()执行结束.")
retCh <- ret
fmt.Println("service()返回值塞进通道.")
}()
return retCh
}
func AsyncServiceOut(service func() string,duration time.Duration) {
select {
case ret := <-AsyncService(service):
fmt.Println("====",ret)
case <-time.After(duration):
fmt.Println("time out")
}
}
func main() {
service:=func() string {
time.Sleep( 3e9)
return "service()的返回值"
}
AsyncServiceOut(service,2e9)
time.Sleep(7e9)
}
```
### 结果截图如下:
![image.png](https://static.studygolang.com/191226/a9fde15d09a8c8e5eb4d14ab12c12ca8.png)
### 下面对这3种进行对比,伤疤来了(注意代码跟上面的不大相同,有更改):
![image.png](https://static.studygolang.com/191227/8a100250c0400836df07a84f2b5c829f.png)
### 上面的大图请用新的标签页打开才是最清晰的!
### 上面的大图3个结果相差不大,结果从左到右分别为:
- 0.00194871445
- 0.00194910536
- 0.00194995740
### 如果你有更加好的写法,请在留言区回复我,让我学习下!感谢!
### 欢迎关注我的[go library demo](https://github.com/AnkoGo/Go-Library-Demo)项目
有疑问加站长微信联系(非本文作者))