迭代时替换通道
replace channel while iterating
我想在某些情况下用新频道替换频道,例如:
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
,并且根据 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 and len(x)
is constant, the range expression is not evaluated.
稍后 for
循环未检查 chStr
变量,因此更改其值无效。
如果你想切换到另一个频道,你不能使用for range
。
只需使用 "normal" 循环并从其中的频道接收。使用特殊形式 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 上试用。
我想在某些情况下用新频道替换频道,例如:
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
,并且根据 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.
稍后 for
循环未检查 chStr
变量,因此更改其值无效。
如果你想切换到另一个频道,你不能使用for range
。
只需使用 "normal" 循环并从其中的频道接收。使用特殊形式 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 上试用。