Goroutines独立地并行运行,因此,如果没有显式同步,您将无法预测执行和完成顺序。因此,您无法将返回的数字与输入的数字配对。
您可以返回更多数据(例如,输入数字和输出,例如包装在结构中),也可以将指针传递到辅助函数(作为新的goroutine发布),例如
*Stuff,让goroutine自己填充计算出的数据
Stuff。返回更多数据
我将使用的信道类型
chan Pair,其中
Pair是:
type Pair struct{ Number, Result int }
因此计算将如下所示:
func doubleNumber(i int, c chan Pair) { c <- Pair{i, i + i} }func powerNumber(i int, c chan Pair) { c <- Pair{i, i * i} }
我将使用a,
map[int]*Stuff因为可收集的数据来自多个渠道(
double和
power),并且我想
Stuff轻松快捷地找到合适的数据(需要指针,因此我也可以在“地图”中对其进行修改)。
所以主要功能:
nums := []int{2, 3, 4} // given numbersstuffs := map[int]*Stuff{}double := make(chan Pair)power := make(chan Pair)for _, i := range nums { go doubleNumber(i, double) go powerNumber(i, power)}// How do I get the values back in the right order?for i := 0; i < len(nums)*2; i++ { getStuff := func(number int) *Stuff { s := stuffs[number] if s == nil { s = &Stuff{Number: number} stuffs[number] = s } return s } select { case p := <-double: getStuff(p.Number).Double = p.Result case p := <-power: getStuff(p.Number).Power = p.Result }}for _, v := range nums { fmt.Printf("%+vn", stuffs[v])}
输出(在Go Playground上尝试):
使用指针&{Number:2 Double:4 Power:4}&{Number:3 Double:6 Power:9}&{Number:4 Double:8 Power:16}
从现在开始我们传递
*Stuff值,我们可以在
Stuff自身中“预填充”输入数字。
但是必须小心,您只能在正确同步的情况下读取/写入值。最简单的方法是等待所有“工人” goroutine完成工作。
var wg = &sync.WaitGroup{}func main() { nums := []int{2, 3, 4} // given numbers stuffs := make([]Stuff, len(nums)) for i, n := range nums { stuffs[i].Number = n wg.Add(2) go doubleNumber(&stuffs[i]) go powerNumber(&stuffs[i]) } wg.Wait() fmt.Printf("%+v", stuffs)}func doubleNumber(s *Stuff) { defer wg.Done() s.Double = s.Number + s.Number}func powerNumber(s *Stuff) { defer wg.Done() s.Power = s.Number * s.Number}
输出(在Go Playground上尝试):
[{Number:2 Double:4 Power:4} {Number:3 Double:6 Power:9} {Number:4 Double:8 Power:16}]
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)