我仍在体验如何充分利用渠道。
我有5个外拨服务电话(大约需要2分钟才能返回),每个电话给我一对返回值。
例如func serviceCall()(T, error)
我想让它们并发,但是我发现代码很长。
基本上,我必须创建5个通道,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
}
答案 0 :(得分:1)
对此没有单一模式。有不同的方法来完成它。最简单的可能是一个等待组,它根本不需要任何通道。模式如下:
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
}
此方法最明显的缺点是您没有灵活性来在发生错误时中止任何未完成的操作。这可能对您无关紧要。
答案 1 :(得分:0)
据我所知,您编写的示例代码中没有反映出您对5个服务呼叫的要求。该示例代码似乎可以工作(我没有运行过进行检查),但没有涵盖您的用例。
我建议从goroutines开始。这个站点和youtube上的链接讲座帮助我开始了解如何管理goroutine。
https://talks.golang.org/2012/concurrency.slide#1
当我在上述谈话中迷路时,此视频也极大地帮助了我: