我仍在体验如何充分利用 channel 。
我有 5 个出站服务调用(大约需要 2 分钟返回),每个都给了我一对返回值。
例如func serviceCall()(T, 错误)
我想让它们并发,但我发现代码很长。
基本上,我必须创建 5 个 channel ,5 个结构来保存返回值。
我写了一个简单的例子来表达这个场景,我想知道这个场景的模式是什么,我如何才能让这段代码变得更好。
主要包
import (
"fmt"
"math/rand"
"time"
"log"
)
// goal: run multiple functions concurrently and process the results.
func main() {
now := time.Now()
// method1
type res1 struct {
news string
err error
}
type res2 struct {
n int
err error
}
ch1 := make(chan *res1)
ch2 := make(chan *res2)
go func() {
var res res1
res.news, res.err = news1()
ch1 <- &res
}()
go func() {
var res res2
res.n, res.err = news2()
ch2 <- &res
}()
one := <-ch1
if one.err != nil {
log.Fatal(one.err)
}
fmt.Println("news1: ", one.news)
two := <-ch2
if two.err != nil {
log.Fatal(two.err)
}
fmt.Println("news2: ", two.n)
fmt.Println("time elapsed: ", time.Since(now))
}
// first sleeps 5 seconds and returns random number or error.
func news1() (string, error) {
time.Sleep(time.Second * 5)
return "new1 is here.", nil
}
// second sleeps random seconds and returns random number or error.
func news2() (int, error) {
n := rand.Intn(20)
time.Sleep(time.Duration(n) * time.Second)
return n, nil
}
最佳答案
对此没有单一的模式。有不同的方法来实现它。最简单的可能是 WaitGroup ,它根本不需要 channel 。这个模式看起来像这样:
func dostuff() {
var result1 int
var result2 string
var resultN SomeStruct
var err1, err2, errN error
wg := sync.WaitGroup{}
wg.Add(1)
go func() {
defer wg.Done()
result1, err1 = doStuff1()
}
wg.Add(1)
go func() {
defer wg.Done()
result2, err2 = doStuff2()
}
// repeat as often as you like
wg.Add(1)
go func() {
defer wg.Done()
resultN, errN = doStuffN()
}
wg.Wait()
// handle results and errors
}
这种方法最明显的缺点是您无法灵活地在出现错误时中止任何未完成的操作。这对您来说可能重要,也可能不重要。
关于go - 同时调用多个服务的模式每个服务返回值和错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56281115/