我有一个文件:
package main
import "fmt"
func
combinations(result chan []byte, len int, min byte, max byte) {
res := make([]byte,len)
for i := 0; i < len; i++ {
res[i] = min
}
result <- res
for true {
i := 0
for i = 0; i < len; i++ {
if res[i] < max {
res[i] = res[i] + 1;
break
} else {
res[i] = 32
}
}
result <- res
if(i == len) {
close(result)
return;
}
}
}
func
main() {
combination_chan := make(chan []byte)
go combinations(combination_chan, 2, 0, 5)
for next_combination := range combination_chan {
fmt.Printf("%x\n",next_combination)
}
}
我希望这能打印0到5之间2个字节的所有可能组合,IE:
0000
0100
...
0001
...
0505
但是,它似乎跳过其他所有值,并打印两次相同的值,IE:
0100
0100
0300
0300
...
为什么要这样做?我在'result&lt; - res'行之前插入了打印件,这些都是正确的。
答案 0 :(得分:2)
如果我们简化一点,Go中的切片基本上是指向数组的指针,因此通过传递一个仍然拥有并通过通道修改的切片,可以创建数据竞争。
没有人知道切片的内容是否在传递到通道的那一刻以及另一个goroutine从通道读取的那一刻被修改。
因此,您的整个算法会导致未定义的行为,因为您只需在修改它们时反复传递相同的内容。
您的案例中的解决方案是在通过频道发送切片之前复制切片:
buf := make([]byte, len(res))
copy(buf, res)
result <- buf
看到它在这里运行:http://play.golang.org/p/ulLYy9Uqnp
另外,我建议不要将len
用作变量名,因为它可能与len()
内置函数冲突。