1

周末刚开始使用 Go,我不确定我是否正确使用了 Go 的特性,或者我是否根本没有做过这种“Go-like”。

该代码应该遍历一个名为的地图的元素,non_placed_alleles并将每个元素与 中的所有元素进行比较,这些元素placed_alleles也存储在地图中。我正在尝试对其中的每个元素使用一个 go-routine,non_placed_alleles因为比较非常昂贵并且需要很长时间。

这是主要功能的一些内容:

runtime.GOMAXPROCS(8) // For 8 consecutive routines at once? got 10 CPUs
c := make(chan string)
for name, alleles := range non_placed_alleles {
    go get_best_places(name, alleles, &placed_alleles, c) 
    // pointer to placed_alleles as we only read, not write - should be safe?
}
for channel_item := range c {
    fmt.Println("This came back ", channel_item)
} 
// This also crashes with "all goroutines are sleeping", 
// but all results are printed

这是被调用的函数:

func get_best_places(name string, alleles []string, placed_alleles *map[string] []string, c chan string) {
    var best_partner string
    // Iterate over all elements of placed_alleles, find best "partner"
    for other_key, other_value := range *placed_alleles {
        best_partner := compare_magic() // omitted because boring
    }
    c <- best_partner
}

有没有办法让这个“更好”?快点?我是否正确使用了指针魔术和 goroutines?

4

1 回答 1

2

一些观察:

  • 您可能想使用缓冲通道

    c := make(chan string, someNumber) // someNumber >= goroutines cca

  • 死锁源于对没有人关闭的通道进行测距(这就是 range 语句终止的方式)。在 Go 中协调事物的机制因任务而异。在这种情况下,有些人可能会使用sync.WaitGroup。请仔细检查位于前面链接下方的示例代码,以获取有关正确使用 WaitGroup 的提示。另一种选择是某种/任何其他类型/方式来计算已启动与已完成的工人(WaitGroup 封装,但我倾向于将其视为矫枉过正)。

  • 在这种情况下,无需传递指向 map 的指针。Go 中的地图具有完整的引用语义(无论如何它只是引擎盖下的一个指针)。

于 2013-02-11T11:10:29.097 回答