dpicx06888 2017-10-24 09:17
浏览 58
已采纳

等待多个goroutines的结果

I am searching a way to execute asynchronously two functions in go which returns different results and errors, wait for them to finish and print both results. Also if one of function returned error I do not want to wait for another function, and just print the error. For example, I have this functions:

func methodInt(error bool) (int, error) {
    <-time.NewTimer(time.Millisecond * 100).C
    if error {
        return 0, errors.New("Some error")
    } else {
        return 1, nil
    }
}

func methodString(error bool) (string, error) {
    <-time.NewTimer(time.Millisecond * 120).C
    if error {
        return "", errors.New("Some error")
    } else {
        return "Some result", nil
    }
}

Here https://play.golang.org/p/-8StYapmlg is how I implemented it, but it has too much code I think. It can be simplified by using interface{} but I don't want to go this way. I want something simpler as, for example, can be implemented in C# with async/await. Probably there is some library that simplifies such operation.

UPDATE: Thank for your responses! It is awesome how fast I got help! I like the usage of WaitGroup. It obviously makes the code more robust to changes, so I easily can add another async method without changing exact count of methods in the end. However, there is still so much code in comparison to same in C#. I know that in go I don't need to explicitly mark methods as async, making them actually to return tasks, but methods call looks much more simple, for example, consider this link actually catching exception is also needed By the way, I found that in my task I actually don't need to know returning type of the functions I want to run async because it will be anyway marshaled to json, and now I just call multiple services in the endpoint layer of go-kit.

  • 写回答

3条回答 默认 最新

  • dqm7854 2017-10-24 18:14
    关注

    You should create two channels for errors and results, then first read errors if no erorrs then read the results, this sample should works for your use case:

    package main
    
    import (
        "errors"
        "sync"
    )
    
    func test(i int) (int, error) {
        if i > 2 {
            return 0, errors.New("test error")
        }
        return i + 5, nil
    }
    
    func test2(i int) (int, error) {
        if i > 3 {
            return 0, errors.New("test2 error")
        }
        return i + 7, nil
    }
    
    func main() {
        results := make(chan int, 2)
        errors := make(chan error, 2)
        var wg sync.WaitGroup
        wg.Add(1)
        go func() {
            defer wg.Done()
            result, err := test(3)
            if err != nil {
                errors <- err
                return
            }
            results <- result
        }()
        wg.Add(1)
        go func() {
            defer wg.Done()
            result, err := test2(3)
            if err != nil {
                errors <- err
                return
            }
            results <- result
        }()
    
        // here we wait in other goroutine to all jobs done and close the channels
        go func() {
            wg.Wait()
            close(results)
            close(errors)
        }()
        for err := range errors {
            // here error happend u could exit your caller function
            println(err.Error())
            return
    
        }
        for res := range results {
            println("--------- ", res, " ------------")
        }
    }
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(2条)

报告相同问题?

悬赏问题

  • ¥15 程序不包含适用于入口点的静态Main方法
  • ¥15 素材场景中光线烘焙后灯光失效
  • ¥15 请教一下各位,为什么我这个没有实现模拟点击
  • ¥15 执行 virtuoso 命令后,界面没有,cadence 启动不起来
  • ¥50 comfyui下连接animatediff节点生成视频质量非常差的原因
  • ¥20 有关区间dp的问题求解
  • ¥15 多电路系统共用电源的串扰问题
  • ¥15 slam rangenet++配置
  • ¥15 有没有研究水声通信方面的帮我改俩matlab代码
  • ¥15 ubuntu子系统密码忘记