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

问题描述 投票:0回答:1

我在玩通道。我有下面这段代码,其中包含一个for循环。我不明白为什么程序似乎每隔一次迭代就跳过一次,也不明白为什么最后的值是0。

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 range c {
        fmt.Println(<-c)
    }
}

输出。

2
4
0
go channel
1个回答
2
投票

你应该先看看golang tour。https:/tour.golang.orgconcurrency4

你在同一时间使用两种不同的读取方式。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.


3
投票

因为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)
    }
}

1
投票

你的罪魁祸首是 range c

https:/play.golang.orgpyGrUhdLAQE-。

你不应该做的范围上 c 相反,你应该使用无限for循环或case语句。

func main() {
    c := make(chan int)
    go send(c)
    for {
        d, ok:= <- c
        if !ok{
          break
        }
        fmt.Println(d)
    }
}

如果你真的想使用range over c 那么你应该这样做

func main() {
    c := make(chan int)
    go send(c)
    for x := range c {
        fmt.Println(x)
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.