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 1
@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 2
用装饰器模式包装函数
```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") }) } |