dougaicha5258 2019-02-01 14:04
浏览 24
已采纳

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

I have a goroutine for a long running job. When the job is done, it pushes the results to a channel. In the meantime, while the job is running, I want to keep updating an API with the status RUNNING.

So far, I have the following code :

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
}

I am new to golang. And I have reached the above code after lot of trial and error, and googling. It's working now. Still it doesn't feel intuitive to me when I look at it (this may very well be because, I am still trying to learn the Go way of doing things). So my question is, can I refactor this into better shape? Is there some existing pattern which is applicable in this kind of scenario? Or if there is some totally different approach to keep sending periodic updates while job is running?

Also, any suggestions to improve upon my golang concurrency are also appreciated. :)

Thanks in advance!

  • 写回答

1条回答 默认 最新

  • drrkgbm6851 2019-02-01 14:15
    关注

    Consider using time.NewTicker, which sends a periodic value to a channel. Here's an example from the documentation:

    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)
            }
        }
    }
    

    Note that the embedded goroutine invoking func emulates a long task by sleeping for 10 seconds, while the caller uses select to wait for the result, while also receiving periodic events from the ticker - this is where you can do the API progress update.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 可见光定位matlab仿真
  • ¥15 arduino 四自由度机械臂
  • ¥15 wordpress 产品图片 GIF 没法显示
  • ¥15 求三国群英传pl国战时间的修改方法
  • ¥15 matlab代码代写,需写出详细代码,代价私
  • ¥15 ROS系统搭建请教(跨境电商用途)
  • ¥15 AIC3204的示例代码有吗,想用AIC3204测量血氧,找不到相关的代码。
  • ¥20 CST怎么把天线放在座椅环境中并仿真
  • ¥15 任务A:大数据平台搭建(容器环境)怎么做呢?
  • ¥15 YOLOv8obb获取边框坐标时报错AttributeError: 'NoneType' object has no attribute 'xywhr'