从概念上讲,这是使用goroutine的正确方法(以及我的代码有什么问题)

时间:2017-09-26 15:57:51

标签: go

我有两个问题:

a)在计算数学结果之类的东西中循环多个goroutine是否有意义?

b)为什么我的代码不起作用(这是我第一次尝试goroutines)?我猜它与关闭频道有关。

package main

import (
    "fmt"
    "math"
    "sync"
)

func main() {
    input := [][]int{
        []int{10, 9},
        []int{5, 2},
        []int{4, 9},
    }

    var wg sync.WaitGroup
    c := make(chan int)
    for _, val := range input {
        wg.Add(1)
        go func(coordinates []int, c chan int) {
            defer wg.Done()
            c <- calculateDistance(coordinates[0], coordinates[1])
        }(val, c)
    }
    distances := []int{}

    for val := range c {
        distances = append(distances, val)
    }
    wg.Wait()
    fmt.Println(distances)
}

func calculateDistance(x int, y int) int {
    v := math.Exp2(float64(x)) + math.Exp2(float64(y))
    distance := math.Sqrt(v)
    return int(distance)
}

游乐场链接:https://play.golang.org/p/0iJ9hFnb8R

2 个答案:

答案 0 :(得分:4)

a)是的,如果你有多个CPU,那么启动多个go例程来执行CPU绑定任务是有意义的。分析代码以查看是否确实有任何好处也非常重要。您可以使用内置benchmark框架中的go来帮助完成此操作。

因为你受到CPU的限制,它可以是一个很好的同步开始,然后将你的goroutine绑定到CPU内核的数量而不是输入列表中的#项,但实际上它应该是指标开车去看。 Go使用基准测试提供了惊人的工具链,并pprof以经验方式确定最有效的方法:)

b)https://play.golang.org/p/zGEQGC9EIy您的频道永远不会关闭,主线程永远不会结束。该示例等待所有例程完成其工作,然后关闭频道。

答案 1 :(得分:2)

当通道关闭时,

通道上的范围循环终止。由于你永远不会关闭你的程序中的频道,主goroutine最终将永远阻止,试图从c接收。

  

在循环中启动多个goroutine是否有意义来计算数学结果?

取决于。如果你还没有看到它,我可以推荐Rob Pike的演讲Concurrency is not parallelism。这可能会给你一些关于它有益的地方以及它不在哪里的直觉。