go - 迭代时替换通道
问题描述
我想在某些情况下用新频道替换频道,例如:
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”,但它不是这样工作的。我不太清楚重新分配频道时发生了什么。有什么建议么?
解决方案
您正在使用for range
, 并且每个规范:对于语句,范围表达式仅评估一次。
范围表达式
x
在循环开始之前计算一次,但有一个例外:如果最多存在一个迭代变量并且len(x)
是常量,则不计算范围表达式。
稍后循环不会检查该chStr
变量for
,因此更改其值无效。
for range
如果要切换到另一个频道,则无法使用。
只需使用“正常”循环并从其中的通道接收。使用特殊形式x, ok := <-ch
,以便您知道通道何时关闭,以便您可以从循环中中断(以模仿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上尝试一下。
推荐阅读
- android - 如何在选项卡布局中将布局放置在固定位置?
- java - 如果页面已经加载,如何使 viewpager 不再加载页面
- reactjs - 使用命名空间或全局对象作为数据源而不是使用道具或状态是否正确?
- php - PHP:在硒测试中发送左、右、上、下箭头键
- javascript - php生成的jquery脚本不适用于同一个php生成的div
- python - 使用 Selenium 和 Python 从下拉列表中选择
- python - 使用 python 和 opencv 模拟 IP 摄像机
- android - mapmyindia API 中的错误
- java - 发送服务器和客户端之间的坐标(Java)
- hadoop - Datanode 已启动但未显示在 dfsadmin -report 中