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

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

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

Go
小怪兽爱吃肉 2022-01-17 10:51:43
在以下代码片段中,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)。
查看完整描述

3 回答

?
侃侃无极

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

len(task) 如果您阅读,则减少 tasks


使用 emptyfor迭代地从任务中读取所有内容。


for {

    select {

    case task := <-tasks:

        fmt.Println(task)

        // Do something

    }

    if len(tasks) == 0 {break}

}

或者,您可以使用范围:


for task := range tasks {


    fmt.Println(task)

    // Do something


    if len(tasks) == 0 {break}

}

break如果你不想锁定你的 goroutine,不要忘记这个循环。


查看完整回答
反对 回复 2022-01-17
?
侃侃尔雅

TA贡献1801条经验 获得超16个赞

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 { ... }

另外,请记住在使用完频道后关闭频道。


查看完整回答
反对 回复 2022-01-17
?
慕尼黑5688855

TA贡献1848条经验 获得超2个赞

因为你从通道中获取元素,它的长度减少了。看看这个样本,我想你会很清楚:https:
//play.golang.org/p/TC3HymIlhs

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

添加回答

举报

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