请问 go 怎么在主程简单对函数进行超时控制 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
The Go Programming Language
http://golang.org/
Go Playground
Go Projects
Revel Web Framework
Askiz
V2EX    Go 编程语言

请问 go 怎么在主程简单对函数进行超时控制

  •  
  •   Askiz 2022-05-18 11:20:46 +08:00 via Android 2978 次点击
    这是一个创建于 1247 天前的主题,其中的信息可能已经有所发展或是发生改变。
    协程的超时控制可以用 select 简单实现,请问如果是在 for 循环里,每次循环执行一个函数,要求对这个函数进行超时控制(超时就直接退出函数),有什么优雅的实现方法?
    19 条回复    2022-05-19 00:34:51 +08:00
    ch2
        1
    ch2  
       2022-05-18 11:24:10 +08:00
    select 已经算是优雅的了
    Askiz
        2
    Askiz  
    OP
       2022-05-18 11:27:14 +08:00 via Android
    @ch2 不好意思,我这边可能说得比较糊,就是主程序里有个函数 RunTask()在运行,怎么对这个函数进行超时控制呢,这个函数不是在协程中运行的
    Herobs
        3
    Herobs  
       2022-05-18 11:29:00 +08:00 via iPhone
    想要”控制”,必然要和 main 分开运行,那不就是要用协程嘛

    或者函数主动实现超时退出,也是要用协程,不过逻辑在函数里面。
    lysS
        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 分钟
    sean4go01
        5
    sean4go01  
       2022-05-18 12:20:16 +08:00
    @Askiz 我最近也遇到类似的问题了,不是协程。我是定时任务,执行一个任务执行比较花时间。应该是执行了一部分后,可能是超时退出了,但是不知道怎么控制这个超时时间。导致后面的任务没执行。
    czyt
        6
    czyt  
       2022-05-18 12:25:48 +08:00
    context
    Juszoe
        7
    Juszoe  
       2022-05-18 12:55:19 +08:00
    前段时间讨论过了 /t/851321
    答案是没有办法从外部强制终止,只能让协程自己退出,比较好的方式是用 context 控制
    lbp0200
        8
    lbp0200  
       2022-05-18 13:05:14 +08:00
    context.WithTimeout
    MarsCloud
        9
    MarsCloud  
       2022-05-18 13:10:02 +08:00   1
    @Askiz 将 RunTask 转成一个 goroutine ,然后通过 select 以及 context 做控制。
    MoYi123
        10
    MoYi123  
       2022-05-18 13:22:20 +08:00
    没办法, 如果是进程 /线程可以通过定时器+kill/tgkill 实现, go 这种自己实现的协程就没有特别好的办法了.
    Askiz
        11
    Askiz  
    OP
       2022-05-18 13:57:30 +08:00 via Android
    @lbp0200 嗯嗯,看来也只能这样了
    Askiz
        12
    Askiz  
    OP
       2022-05-18 14:02:04 +08:00 via Android
    @Herobs 我想实现的是对 mysql 进行连接测试,发现这个标准库并没有超时控制,而 ssh 的连接测试是有自带一个 timeout 参数的。不过看了 net.DialTimeout 函数发现这个也是用多开一个 go 程+select 实现超时控制的。看来也只能用 go 程了。
    EZVIK
        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.")
    }

    ```
    FrankAdler
        14
    FrankAdler  
       2022-05-18 16:22:11 +08:00
    为什么要拒绝使用 goroutine 呢,配上 context 非常优雅了
    Askiz
        15
    Askiz  
    OP
       2022-05-18 18:39:28 +08:00 via Android
    学到了,感谢~
    Askiz
        16
    Askiz  
    OP
       2022-05-18 19:20:00 +08:00
    @EZVIK #13 感觉这么多闭包没必要呀,直接 ch <- fun(i) 不就可以了
    Kisesy
        17
    Kisesy  
       2022-05-18 20:03:00 +08:00
    测试 mysql 连接? 用这个库 github.com/go-sql-driver/mysql ?
    这个库不是可以带有 timeout 参数吗?
    Askiz
        18
    Askiz  
    OP
       2022-05-18 21:08:50 +08:00 via Android
    @Kisesy 嗯嗯,我后来发现了
    raw0xff
        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")
    })
    }
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     870 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 26ms UTC 21:01 PVG 05:01 LAX 14:01 JFK 17:01
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86