为了账号安全,请及时绑定邮箱和手机立即绑定

在 for 循环中写入通道会跳过迭代

在 for 循环中写入通道会跳过迭代

Go
千巷猫影 2022-06-06 17:44:23
我正在玩频道。我在下面有这段代码,其中包含一个 for 循环。我不明白为什么程序似乎跳过了所有其他迭代,以及为什么最后一个值为 0。package mainimport (    "fmt"    "time")func send(c chan int) {    for i := 1; i < 6; i++ {        time.Sleep(time.Second)        c <- i    }    close(c)}func main() {    c := make(chan int)    go send(c)    for range c {        fmt.Println(<-c)    }}输出:240
查看完整描述

3 回答

?
动漫人物

TA贡献1815条经验 获得超10个赞

因为 range 从通道中获取一个值,所以正确的代码看起来像这样


package main


import (

    "fmt"

    "time"

)


func send(c chan int) {

    for i := 1; i < 6; i++ {

        time.Sleep(time.Second)

        c <- i

    }

    close(c)

}


func main() {

    c := make(chan int)

    go send(c)

    for value := range c {

        fmt.Println(value)

    }

}


查看完整回答
反对 回复 2022-06-06
?
繁星淼淼

TA贡献1775条经验 获得超11个赞

您应该先查看 golang 之旅。 https://tour.golang.org/concurrency/4


您同时使用两种不同的读取方式:

for range c从 c 通道读取一次,然后再次从通道读取<-c


如果您想写出您发送到频道的内容,只需使用以下选项之一:


for value := range c {

  fmt.Println(value)

}


OR


for {

  select {

  case value, ok := <- c:

    if !ok {

      return

    }

    fmt.Println(value)

  }

}

因为您有奇数次迭代(1..5),所以最后一个 0 出现是因为从封闭通道读取(类型的默认值)。


如果您使用value, ok := <-c并且在读取时通道已关闭,则该值将始终为默认值,并且ok将为false.


查看完整回答
反对 回复 2022-06-06
?
摇曳的蔷薇

TA贡献1793条经验 获得超6个赞

你的罪魁祸首是range c


https://play.golang.org/p/yGrUhdLAQE-


您不应该使用 range onc而是应该使用无限 for 循环或 case 语句。


func main() {

    c := make(chan int)

    go send(c)

    for {

        d, ok:= <- c

        if !ok{

          break

        }

        fmt.Println(d)

    }

}

虽然如果你真的想使用 range overc那么你应该做这样的事情


func main() {

    c := make(chan int)

    go send(c)

    for x := range c {

        fmt.Println(x)

    }

}


查看完整回答
反对 回复 2022-06-06
  • 3 回答
  • 0 关注
  • 119 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信