我想在某种情况下用新 channel 替换 channel ,例如:
package main
import (
"log"
"time"
)
func subMsg(s string) chan string {
ch := make(chan string)
go func() {
ticker := time.NewTicker(time.Second * 2)
for range ticker.C {
ch <- s
}
}()
return ch
}
func main() {
chStr := subMsg("hello")
go func() {
i := 0
for s := range chStr {
log.Print(s)
i++
if i > 5 {
log.Print("new topic")
i = 0
chStr = subMsg("world")
}
}
}()
select {}
}
我希望此代码段输出5个“hello”,然后是“world”,但这种方式无法正常工作。我不太清楚重新分配 channel 时发生了什么。有什么建议?
最佳答案
您正在使用for range
,并且对于Spec: For statements,范围表达式仅被评估一次。
The range expression
x
is evaluated once before beginning the loop, with one exception: if at most one iteration variable is present andlen(x)
is constant, the range expression is not evaluated.
稍后,
chStr
循环将不检查for
变量,因此更改其值无效。如果要切换到另一个 channel ,则不能使用
for range
。只需使用“正常”循环并从其内部的 channel 接收信号即可。使用特殊形式的
x, ok := <-ch
,您可以知道 channel 何时关闭,因此可以从循环中中断(以模仿for range
的工作原理):for {
s, ok := <-chStr
if !ok {
break
}
log.Print(s)
i++
if i > 5 {
log.Print("new topic")
i = 0
chStr = subMsg("world")
}
}
在Go Playground上尝试一下。
关于go - 迭代时替换 channel ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59679132/