如何在 Go API 中并发运行函数,而不是顺序运行函数?

在API中,如果我们需要查询多个表,我们如何同时实现它,而不是遵循顺序方式,即


func sampleAPI(w http.ResponseWriter, r *http.Request) {

    a, err := getFromATable();  //1

    if err != nil {

       w.WriteHeader(http.StatusInternalServerError)

       return

    }

    b, err := getFromBTable();  //2

    if err != nil {

       w.WriteHeader(http.StatusInternalServerError)

       return

    }

    c, err := getFromCTable();  //3

    if err != nil {

       w.WriteHeader(http.StatusInternalServerError)

       return

    }

    .

    .

    .

}

我想同时调用上述函数1,2,3。我怎样才能做到这一点


料青山看我应如是
浏览 104回答 3
3回答

手掌心

使用错误通道进行同步func sampleAPI(w http.ResponseWriter, r *http.Request) {&nbsp; &nbsp; chErr := make(chan error)&nbsp; &nbsp; var a correctType&nbsp; &nbsp; go func() {&nbsp; &nbsp; &nbsp; &nbsp; var err error&nbsp; &nbsp; &nbsp; &nbsp; a, err = getFromATable()&nbsp; &nbsp; &nbsp; &nbsp; chErr <- err&nbsp; &nbsp; }()&nbsp; &nbsp; var b correctType&nbsp; &nbsp; go func() {&nbsp; &nbsp; &nbsp; &nbsp; var err error&nbsp; &nbsp; &nbsp; &nbsp; b, err = getFromBTable()&nbsp; &nbsp; &nbsp; &nbsp; chErr <- err&nbsp; &nbsp; }()&nbsp; &nbsp; var c correctType&nbsp; &nbsp; go func() {&nbsp; &nbsp; &nbsp; &nbsp; var err error&nbsp; &nbsp; &nbsp; &nbsp; c, err = getFromCTable()&nbsp; &nbsp; &nbsp; &nbsp; chErr <- err&nbsp; &nbsp; }()&nbsp; &nbsp; var err error&nbsp; &nbsp; for i := 0; i < 3; i++ {&nbsp; &nbsp; &nbsp; &nbsp; if r := <-chErr; r != nil {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; err = r&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }&nbsp; &nbsp; if err != nil {&nbsp; &nbsp; &nbsp; &nbsp; w.WriteHeader(http.StatusInternalServerError)&nbsp; &nbsp; &nbsp; &nbsp; // etc.&nbsp; &nbsp; &nbsp; &nbsp; return&nbsp; &nbsp; }&nbsp; &nbsp; // continue to do stuff with a, b, c}一些注意事项:每个 go 函数都必须向 添加一个值。确保它!如果没有错误,则写入(如果没有错误,此示例将写入)。chErrnilchErrfor 循环必须迭代与启动 go 函数相同的数量。for 循环确保所有函数都已完成(有或没有错误),然后再继续。使用错误进行同步很方便,因为它对于所有函数都是相同的类型。返回类型可能不同。如果我们需要在错误时取消,我们无论如何都需要将错误从goroutines中取回。使用errgroup正如 @Зелёный 在注释中所建议的那样,这里有一个使用(仍然)实验包错误组的示例:func sampleAPI(w http.ResponseWriter, r *http.Request) {&nbsp; &nbsp; g, ctx := errgroup.WithContext(context.TODO())&nbsp; &nbsp; var a correctType&nbsp; &nbsp; g.Go(func() (err error) {&nbsp; &nbsp; &nbsp; &nbsp; a, err = getFromATable(ctx)&nbsp; &nbsp; &nbsp; &nbsp; return err&nbsp; &nbsp; })&nbsp; &nbsp; var b correctType&nbsp; &nbsp; g.Go(func() (err error) {&nbsp; &nbsp; &nbsp; &nbsp; b, err = getFromBTable(ctx)&nbsp; &nbsp; &nbsp; &nbsp; return err&nbsp; &nbsp; })&nbsp; &nbsp; var c correctType&nbsp; &nbsp; g.Go(func() (err error) {&nbsp; &nbsp; &nbsp; &nbsp; c, err = getFromCTable(ctx)&nbsp; &nbsp; &nbsp; &nbsp; return err&nbsp; &nbsp; })&nbsp; &nbsp; if err := g.Wait(); err != nil {&nbsp; &nbsp; &nbsp; &nbsp; w.WriteHeader(http.StatusInternalServerError)&nbsp; &nbsp; &nbsp; &nbsp; // etc.&nbsp; &nbsp; &nbsp; &nbsp; return&nbsp; &nbsp; }&nbsp; &nbsp; // continue to do stuff with a, b, c}一些注意事项:这个检查所有错误,并为您返回第一个错误。如果一个错误,它还会取消剩余的调用(因此ctx)它使用sync.WaitGroup缺点:它是一个额外的依赖项,因为它不是标准库的一部分(尚未)。使用WaitGroup还可以使用 a 来等待所有函数都返回其结果。sync.WaitGroupfunc sampleAPI(w http.ResponseWriter, r *http.Request) {&nbsp; &nbsp; var wg sync.WaitGroup&nbsp; &nbsp; wg.Add(3)&nbsp; &nbsp; var a correctType&nbsp; &nbsp; var errA error&nbsp; &nbsp; go func() {&nbsp; &nbsp; &nbsp; &nbsp; defer wg.Done()&nbsp; &nbsp; &nbsp; &nbsp; a, errA = getFromATable()&nbsp; &nbsp; }()&nbsp; &nbsp; var b correctType&nbsp; &nbsp; var errB error&nbsp; &nbsp; go func() {&nbsp; &nbsp; &nbsp; &nbsp; defer wg.Done()&nbsp; &nbsp; &nbsp; &nbsp; b, errB = getFromBTable()&nbsp; &nbsp; }()&nbsp; &nbsp; var c correctType&nbsp; &nbsp; var errC error&nbsp; &nbsp; go func() {&nbsp; &nbsp; &nbsp; &nbsp; defer wg.Done()&nbsp; &nbsp; &nbsp; &nbsp; c, errC = getFromCTable()&nbsp; &nbsp; }()&nbsp; &nbsp; wg.Wait()&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; if errA != nil {&nbsp; &nbsp; &nbsp; &nbsp; w.WriteHeader(http.StatusInternalServerError)&nbsp; &nbsp; &nbsp; &nbsp; // etc.&nbsp; &nbsp; &nbsp; &nbsp; return&nbsp; &nbsp; }&nbsp; &nbsp; if errB != nil {&nbsp; &nbsp; &nbsp; &nbsp; w.WriteHeader(http.StatusInternalServerError)&nbsp; &nbsp; &nbsp; &nbsp; // etc.&nbsp; &nbsp; &nbsp; &nbsp; return&nbsp; &nbsp; }&nbsp; &nbsp; if errC != nil {&nbsp; &nbsp; &nbsp; &nbsp; w.WriteHeader(http.StatusInternalServerError)&nbsp; &nbsp; &nbsp; &nbsp; // etc.&nbsp; &nbsp; &nbsp; &nbsp; return&nbsp; &nbsp; }&nbsp; &nbsp; // continue to do stuff with a, b, c}一些注意事项:这里需要 3 个错误变量。您需要在 之后检查所有3个错误变量,使其有点冗长。wg.Wait

慕码人8056858

您还可以使用等待组来等待所有 api 调用完成,然后再继续操作:func sampleAPI(w http.ResponseWriter, r *http.Request) {&nbsp; &nbsp; var res1, res2, res3 myCustomType&nbsp; &nbsp; var err1, err2, err2 error&nbsp; &nbsp; var wg sync.WaitGroup&nbsp; &nbsp; &nbsp; &nbsp; wg.Add(3)&nbsp; &nbsp; go func() {&nbsp; &nbsp; &nbsp; &nbsp; defer wg.Done()&nbsp; &nbsp; &nbsp; &nbsp; res1, err1 = getFromATable();&nbsp; //1&nbsp; &nbsp; }()&nbsp; &nbsp; go func() {&nbsp; &nbsp; &nbsp; &nbsp; defer wg.Done()&nbsp; &nbsp; &nbsp; &nbsp; res2, err2 = getFromBTable();&nbsp; //2&nbsp; &nbsp; }()&nbsp; &nbsp; go func() {&nbsp; &nbsp; &nbsp; &nbsp; defer wg.Done()&nbsp; &nbsp; &nbsp; &nbsp; res3, err3 = getFromXTable();&nbsp; //3&nbsp; &nbsp; }()&nbsp; &nbsp; wg.Wait()}进一步参考也 https://gobyexample.com/waitgroups 和 https://tutorialedge.net/golang/go-waitgroup-tutorial/

慕妹3146593

如果 a、b 和 c 是不同的类型,则可以尝试以下方法。interface{}类型只是为了展示如何编码,你可以根据自己的要求修改通道类型。&nbsp; &nbsp; aCh := make(chan interface{})&nbsp; &nbsp; bCh := make(chan interface{})&nbsp; &nbsp; cCh := make(chan interface{})&nbsp; &nbsp; defer close(aCh)&nbsp; &nbsp; defer close(bCh)&nbsp; &nbsp; defer close(cCh)&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; go func() {&nbsp; &nbsp; &nbsp; a, _ := GetFromATable()&nbsp; &nbsp; &nbsp; aCh <- a&nbsp; &nbsp; }()&nbsp; &nbsp; go func() {&nbsp; &nbsp; &nbsp; b, _ := GetFromBTable()&nbsp; &nbsp; &nbsp; bCh <- b&nbsp; &nbsp; }()&nbsp; &nbsp; go func() {&nbsp; &nbsp; &nbsp; c, _ := GetFromCTable()&nbsp; &nbsp; &nbsp; cCh <- c&nbsp; &nbsp; }()&nbsp; &nbsp; fmt.Println(<- aCh, <- bCh, <- cCh)如果所有三个输出都处于同一类型,则只需使用单个通道或使用带有 select 语句的 forever for 循环来处理流式处理要求。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go