如何解决从 goroutine 中获取结果的最佳方法
我有两个无法更改的函数(请参阅下面的 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,fmt.Errorf("empty name is not allowed")
}
fmt.Println("processing second")
return fmt.Sprintf("Second hello %s",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
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。