go - 迭代时替换 channel

标签 go channel

我想在某种情况下用新 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 and len(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/

相关文章:

go - 在 Go 中表示其中一个/联合的惯用方式

google-app-engine - 为 webRTC 视频聊天创建 channel

即使使用 WaitGroup 同步,Goroutine 已启动但未执行或部分执行

select - Go语言——为多个select case运行相同的代码

postgresql - 如何将行从 STDIN 导入到 Postgresql?

go - 为什么我不能对类型 validator.FieldError 使用 Error()

image - 更改单个像素的颜色 - Golang 图像

go - 从大文本中删除所有非字母数字字符的有效方法

go - 如何通过 channel 传递压缩字节?

go - channel 多路复用器