一尘不染

等待多个goroutines的结果

go

我正在寻找一种方法来异步执行go中的两个函数,该函数返回不同的结果和错误,等待它们完成并打印两个结果。另外,如果一个函数返回错误,我不想等待另一个函数,只打印错误。例如,我具有以下功能:

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

这里https://play.golang.org/p/-8StYapmlg是我是如何实现它,但是它有太多的代码,我想。可以通过使用interface
{}来简化它,但是我不想这样。我想要更简单的东西,例如,可以使用Async / await在C#中实现。可能有一些库可以简化这种操作。

更新:感谢您的回复!我得到帮助的速度真是太棒了!我喜欢使用WaitGroup。显然,它使代码对更改更健壮,因此我可以轻松地添加另一个异步方法,而无需最终更改方法的确切数量。但是,与C#中的代码相比,仍有太多代码。我知道在执行过程中,我不需要显式将方法标记为异步,从而使它们实际上可以返回任务,但是方法调用看起来要简单得多,例如,考虑到实际上也需要捕获异常的链接
,我发现在我的任务中,我实际上不需要知道我想运行异步函数的返回类型,因为无论如何它将被封送到json,现在我只是在go-kit的端点层中调用了多个服务。


阅读 184

收藏
2020-07-02

共1个答案

一尘不染

您应该为错误和结果创建两个通道,然后,如果没有错误,则先读取错误,然后再读取结果,此示例适用于您的用例:

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, " ------------")
    }
}
2020-07-02