![]() | 1 ch2 2022-05-18 11:24:10 +08:00 select 已经算是优雅的了 |
2 Askiz OP @ch2 不好意思,我这边可能说得比较糊,就是主程序里有个函数 RunTask()在运行,怎么对这个函数进行超时控制呢,这个函数不是在协程中运行的 |
3 Herobs 2022-05-18 11:29:00 +08:00 via iPhone 想要”控制”,必然要和 main 分开运行,那不就是要用协程嘛 或者函数主动实现超时退出,也是要用协程,不过逻辑在函数里面。 |
![]() | 4 lysS 2022-05-18 11:40:53 +08:00 那么这个函数里面必须有 for 循环,每次循环的时候判断一下。其实就是这个函数要是可分的、不一定是循环。 比如 func a(){ time.Sleep(time.Hour) } 就不行,而 func b(){ time.Sleep(time.Minute) time.Sleep(time.Minute) time.Sleep(time.Minute) } 就可以,超时时间精度是 1 分钟 |
5 sean4go01 2022-05-18 12:20:16 +08:00 @Askiz 我最近也遇到类似的问题了,不是协程。我是定时任务,执行一个任务执行比较花时间。应该是执行了一部分后,可能是超时退出了,但是不知道怎么控制这个超时时间。导致后面的任务没执行。 |
![]() | 6 czyt 2022-05-18 12:25:48 +08:00 context |
![]() | 8 lbp0200 2022-05-18 13:05:14 +08:00 context.WithTimeout |
9 MarsCloud 2022-05-18 13:10:02 +08:00 ![]() @Askiz 将 RunTask 转成一个 goroutine ,然后通过 select 以及 context 做控制。 |
![]() | 10 MoYi123 2022-05-18 13:22:20 +08:00 没办法, 如果是进程 /线程可以通过定时器+kill/tgkill 实现, go 这种自己实现的协程就没有特别好的办法了. |
12 Askiz OP @Herobs 我想实现的是对 mysql 进行连接测试,发现这个标准库并没有超时控制,而 ssh 的连接测试是有自带一个 timeout 参数的。不过看了 net.DialTimeout 函数发现这个也是用多开一个 go 程+select 实现超时控制的。看来也只能用 go 程了。 |
![]() | 13 EZVIK 2022-05-18 14:15:39 +08:00 ![]() 用装饰器模式包装函数 ```go type RunTask func(int) float64 func RunTaskTimeout(fun RunTask, timeout time.Duration) RunTask { return func(i int) float64 { ch := make(chan float64) go func() { ch <- func(i int) float64 { return func(i int) float64 { return fun(i) }(i) }(i) }() select { case f := <-ch: return f case <-time.After(timeout): return -1 } } } func main() { runTask := RunTaskTimeout(Pi, time.Second) data := []int{500, 5000, 50000, 500000, 5000000} for i := 0; i < 10; i++ { if res := runTask(data[i]); res < 0 { break } else { fmt.Println(res) } } fmt.Println("DONE.") } ``` |
14 FrankAdler 2022-05-18 16:22:11 +08:00 为什么要拒绝使用 goroutine 呢,配上 context 非常优雅了 |
15 Askiz OP 学到了,感谢~ |
![]() | 17 Kisesy 2022-05-18 20:03:00 +08:00 测试 mysql 连接? 用这个库 github.com/go-sql-driver/mysql ? 这个库不是可以带有 timeout 参数吗? |
19 raw0xff 2022-05-19 00:34:51 +08:00 我是这么干的,感觉没那么优雅 func main(){ go stopit() } func stopit() { time.AfterFunc(3*time.Second, func() { log.Println("stop it") }) } |