为什么选择案例将我的 for 循环减半?

在以下代码片段中,tasks是一个长度为 30 的缓冲通道,其中填充了正好 30 个元素。我正在编写一个for循环来操作从通道中读取的每个任务。


for i := 0; i < len(tasks); i++ {

    fmt.Println(i)

    select {

      case task := <-tasks: 

        fmt.Println(task)

        // Do something


    }

}


fmt.Println("Done")

但是,这个 for 循环只从 0 运行到 14。当我改变这个通道的长度(这取决于我拥有的任务元素的数量)时,for 循环总是只运行len(tasks). 为什么会这样?


背景:我对任务使用缓冲通道,因为我打算在 goroutine 中执行每个任务,如果任务失败,则会处理任务。但我目前已将代码缩减为 for 循环中的选择案例,我对为什么选择案例导致 for 循环仅执行一半时间感到困惑。我确认这个for循环已经完成执行,并且在最后一次执行之后,i等于14(通道长度为30)。


小怪兽爱吃肉
浏览 179回答 3
3回答

侃侃无极

len(task) 如果您阅读,则减少 tasks使用 emptyfor迭代地从任务中读取所有内容。for {&nbsp; &nbsp; select {&nbsp; &nbsp; case task := <-tasks:&nbsp; &nbsp; &nbsp; &nbsp; fmt.Println(task)&nbsp; &nbsp; &nbsp; &nbsp; // Do something&nbsp; &nbsp; }&nbsp; &nbsp; if len(tasks) == 0 {break}}或者,您可以使用范围:for task := range tasks {&nbsp; &nbsp; fmt.Println(task)&nbsp; &nbsp; // Do something&nbsp; &nbsp; if len(tasks) == 0 {break}}break如果你不想锁定你的 goroutine,不要忘记这个循环。

侃侃尔雅

len(tasks)在每次迭代中重新评估。所以值是 30,然后是 29,然后是 28,......最后,在中间len(tasks)交叉i,这就是为什么它只打印一半的值。因此,您可以做的是将长度存储在变量中:n := len(tasks)for i := 0; i < n; i++ { ... }或者,你可以简单地写for len(tasks) > 0 { ... }如果你想消耗所有元素,range操作符可以工作:for task := range tasks { ... }另外,请记住在使用完频道后关闭频道。

慕尼黑5688855

因为你从通道中获取元素,它的长度减少了。看看这个样本,我想你会很清楚:https://play.golang.org/p/TC3HymIlhs
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go