登录
首页 >  Golang >  Go问答

从 goroutine 中获取结果的最佳方法

来源:stackoverflow

时间:2024-04-14 13:33:35 433浏览 收藏

哈喽!今天心血来潮给大家带来了《从 goroutine 中获取结果的最佳方法》,想必大家应该对Golang都不陌生吧,那么阅读本文就都不会很困难,以下内容主要涉及到,若是你正在学习Golang,千万别错过这篇文章~希望能帮助到你!

问题内容

我有两个无法更改的函数(请参阅下面的 first()second() )。它们返回一些数据和错误(输出数据不同,但在下面的示例中,为了简单起见,我使用 (string, error)

我想在单独的 goroutine 中运行它们 - 我的方法:

package main

import (
    "fmt"
    "os"
)

func first(name string) (string, error) {
    if name == "" {
        return "", fmt.Errorf("empty name is not allowed")
    }
    fmt.Println("processing first")
    return fmt.Sprintf("First hello %s", name), nil
}

func second(name string) (string, error) {
    if name == "" {
        return "", fmt.Errorf("empty name is not allowed")
    }
    fmt.Println("processing second")
    return fmt.Sprintf("Second hello %s", name), nil
}

func main() {
    firstCh := make(chan string)
    secondCh := make(chan string)
    
    go func() {
        defer close(firstCh)
        res, err := first("one")
        if err != nil {
            fmt.Printf("Failed to run first: %v\n", err)
        }
        firstCh <- res
    }()

    go func() {
        defer close(secondCh)
        res, err := second("two")
        if err != nil {
            fmt.Printf("Failed to run second: %v\n", err)
        }
        secondCh <- res
    }()

    resultsOne := <-firstCh
    resultsTwo := <-secondCh

    // It's important for my app to do error checking and stop if errors exist.
    if resultsOne == "" || resultsTwo == "" {
        fmt.Println("There was an ERROR")
        os.Exit(1)
    }

    fmt.Println("ONE:", resultsOne)
    fmt.Println("TWO:", resultsTwo)
}

我相信一个警告是 resultsone := <-firstch 会阻塞,直到第一个 goroutine 完成,但我不太关心这个

您能确认我的方法好吗?对于我的情况,还有哪些其他方法会更好?


解决方案


这个例子看起来大部分都不错。一些改进是:

  • 将您的通道声明为缓冲通道
firstch := make(chan string, 1)
   secondch := make(chan string, 1)

对于无缓冲的通道,发送操作会阻塞(直到有人接收)。如果你的 goroutine #2 比第一个快得多,它也必须等到第一个完成,因为你按顺序接收:

resultsone := <-firstch // waiting on this one first
    resultstwo := <-secondch // sender blocked because the main thread hasn't reached this point
  • 使用 "golang.org/x/sync/errgroup".group。该程序会让人感觉“不太原生”,但它使您无需手动管理通道 - 在非人为设置中进行交易,以同步结果上的写入:
func main() {
    var (
        resultsOne string
        resultsTwo string
    )

    g := errgroup.Group{}
    
    g.Go(func() error {
        res, err := first("one")
        if err != nil {
            return err
        }
        resultsOne = res
        return nil
    })

    g.Go(func() error {
        res, err := second("two")
        if err != nil {
            return err
        }
        resultsTwo = res
        return nil
    })

    err := g.Wait()
    // ... handle err

理论要掌握,实操不能落!以上关于《从 goroutine 中获取结果的最佳方法》的详细介绍,大家都掌握了吧!如果想要继续提升自己的能力,那么就来关注golang学习网公众号吧!

声明:本文转载于:stackoverflow 如有侵犯,请联系study_golang@163.com删除
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>