我已经通读了CommonMistakes,并通过-race标志运行了我的代码,但我似乎找不到这里的错误所在:
package main
import (
"fmt"
)
func main() {
i := 1
totalHashFields := 6
for i <= totalHashFields {
Combinations(totalHashFields, i, func(c []int) {
fmt.Println("Outside goroutine:", c)
go func(c []int) {
fmt.Println("Inside goroutine:", c)
}(c)
})
i++
}
}
func Combinations(n, m int, emit func([]int)) {
s := make([]int, m)
last := m - 1
var rc func(int, int)
rc = func(i, next int) {
for j := next; j < n; j++ {
s[i] = j
if i == last {
emit(s)
} else {
rc(i+1, j+1)
}
}
return
}
rc(0, 0)
}
(对于感兴趣的人,组合函数是一个组合algo )
以下是fmt.Println的一些输出:
Outside goroutine: [0 1 4]
Inside goroutine: [5 5 5]
Outside goroutine: [0 1 2 3 4 5]
Inside goroutine: [5 5 5 5 5 5]
基本上,即使我将c作为参数传递给匿名go函数,该值也始终与此作用域之外的值不同。在上面的输出中,我期望2个“内部”值也分别为0 1 4和0 1 2 3 4 5。
发布于 2017-03-07 19:32:41
问题是你goroutine上的所有工作都是在distinc int切片上进行的,但是这些工作都共享一个公共的后备数组:在完成Combinations
之后,s
中的5
将会充满主数组,你的c
和s共享底层的后备数组。
但是您的goroutines只有在Combinations
完成后才会开始执行,所以一旦它们启动,就会看到s
的最终值只有5s。
在这里,像您一样传入切片没有什么帮助,因为这会生成c
的正确副本,而不是支持数组的副本。
试一试
Combinations(totalHashFields, i, func(c []int) {
fmt.Println("Outside goroutine:", c)
cpy := make([]int, len(c))
copy(cpy, c)
go func(c []int) {
fmt.Println("Inside goroutine:", c)
}(cpy)
})
来制作c语言的“深度拷贝”。
https://stackoverflow.com/questions/42646131
复制相似问题