如何从长期运行的goroutine发送更新?

时间:2019-02-01 14:04:58

标签: go

我有一个长期工作的goroutine。当任务完成时,它推动的结果的通道。在此期间,作业运行的同时,我想保持状态为RUNNING更新的API。

到目前为止,我有以下代码:

func getProgressTimeout() <-chan time.Time {
    return time.After(5 * time.Minute)
}

func runCommand(arg *Request) {
    chanResult := make(chan Results)

    go func(args *Request, c chan Results) {
        resp, err := execCommand(args)
        c <- Results{
            resp: resp,
            err:  err,
        }
    }(arg, chanResult)

    var err error

progressLoop:
    for {
        select {
        case <-getProgressTimeout():
            updateProgress()  // this method will send status= RUNNING to a REST API

        case out := <-chanResult:
            err = jobCompleted(request, out)
            break progressLoop
        }
    }
    return err
}

我是golang的新手。经过大量的反复试验和谷歌搜索,我已经到达了上面的代码。现在正在工作。不过它不觉得直观的我,当我看着它(这很可能是因为,我仍然努力学习做事的方式去)。所以我的问题是,我可以将其重构为更好的形状吗?是否存在一些适用于这种情况的现有模式?或者,如果有一些完全不同的方法,以保持工作运行的同时发送定期更新?

此外,任何建议,以改善在我golang并发还赞赏。 :)

谢谢!

1 个答案:

答案 0 :(得分:3)

请考虑使用time.NewTicker,它将周期值发送到通道。这是文档中的示例:

package main

import (
    "fmt"
    "time"
)

func main() {
    ticker := time.NewTicker(time.Second)
    defer ticker.Stop()
    done := make(chan bool)
    go func() {
        time.Sleep(10 * time.Second)
        done <- true
    }()
    for {
        select {
        case <-done:
            fmt.Println("Done!")
            return
        case t := <-ticker.C:
            fmt.Println("Current time: ", t)
        }
    }
}

请注意,嵌入式goroutine调用func通过休眠10秒钟来模拟一个长任务,而调用方使用select等待结果,同时还接收来自自动收报器的定期事件-这是您可以在其中进行API进度更新。