在尝试几个频道实验时,我想出了下面的代码:
var strChannel = make(chan string, 30)
var mutex = &sync.Mutex{}
func main() {
go sampleRoutine()
for i := 0; i < 10; i++ {
mutex.Lock()
strChannel <- strconv.FormatInt(int64(i), 10)
mutex.Unlock()
time.Sleep(1 * time.Second)
}
time.Sleep(10 * time.Second)
}
func sampleRoutine() {
/* A: for msg := range strChannel{*/
/* B: for {
msg := <-strChannel*/
log.Println("got message ", msg, strChannel)
if msg == "3" {
mutex.Lock()
strChannel = make(chan string, 20)
mutex.Unlock()
}
}
}基本上在这里,在听给定的通道时,我将信道变量在特定的条件下分配给一个新的通道(当msg == 3时)。
当我在注释块B中使用代码时,它按预期工作,即循环移动到新创建的通道并打印4-10。
然而,注释块A,我认为这只是一种不同的方式写循环不工作,即在打印"3“,它停止。
有人能告诉我这种行为的原因吗?
在这样的代码中,一个例行监听通道,创建一个新的通道安全吗?
发布于 2018-07-02 14:02:25
在Go中,for语句在循环开始前计算range右侧的值。
这意味着更改range右侧变量的值不会产生任何影响。因此,在您的代码中,在变体A中,msg总是在原始通道上迭代,并且从未改变过。在Varaint中,它按照预期的方式工作,因为每次迭代都要对通道进行评估。
这个概念有点棘手。这并不意味着您不能在slice或map的右侧修改range的项。如果深入研究它,您会发现在Go中,map和slice存储一个指针,而修改它的项不会更改该指针,因此它会产生效果。
在array的情况下,这就更加棘手了。修改array在range右侧的项没有任何影响。这是由于Go将数组存储为值的机制。
发布于 2018-07-02 13:35:31
strChannel是错误的。别干那事。即使是B变体也不行。将range strChannel想象为“请在当前存储在变量strChannel中的通道中的值范围内”。这个范围将“在原始通道上继续”,并且在同一个变量中存储一个新通道不会改变这一点。避免这样的代码!https://stackoverflow.com/questions/51137056
复制相似问题