goroutine只通过通道传递一半的值

时间:2015-10-08 15:52:46

标签: go

我有一个文件:

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'行之前插入了打印件,这些都是正确的。

1 个答案:

答案 0 :(得分:2)

如果我们简化一点,Go中的切片基本上是指向数组的指针,因此通过传递一个仍然拥有并通过通道修改的切片,可以创建数据竞争。

没有人知道切片的内容是否在传递到通道的那一刻以及另一个goroutine从通道读取的那一刻被修改。

因此,您的整个算法会导致未定义的行为,因为您只需在修改它们时反复传递相同的内容。

您的案例中的解决方案是在通过频道发送切片之前复制切片:

buf := make([]byte, len(res))
copy(buf, res)
result <- buf

看到它在这里运行:http://play.golang.org/p/ulLYy9Uqnp

另外,我建议不要将len用作变量名,因为它可能与len()内置函数冲突。