首页 > 解决方案 > 是否可以在“for .. range”循环中的每次迭代后添加最终语句(如标准 for 循环)?

问题描述

在一个for task := range ch {..}循环中(遍历一个通道),我有几个地方想要前进到下一个元素(continue);但是,我需要在 continue 之前执行一个附加语句(设置一个标志来标记工作例程当前处于空闲状态),但在从通道接收到下一个元素之前 - 请参见下面的代码示例。

目前,我必须在每个continue. 这可行,但不是很优雅,而且worker.setIdle()很容易被遗忘。如果我可以在循环的入口处设置这样一个“终结器”语句,那就太好了,就像你对for task := range ch; worker.setIdle() {...}构造的期望一样,但这当然在语法上是不正确的。这就像一个defer循环,它在每次循环迭代结束时执行,而不是在函数结束时执行。有没有办法在 Go 中表达这一点?

for task := range ch {
  ...
  if (...) {
    ...
    worker.setIdle()
    continue
  }
  ...
  if (...) {
    ...
    worker.setIdle()
    continue
  }
  ...
  if (...) {
    ...
    worker.setIdle()
    continue
  }
  ...
  worker.setIdle()
}

编辑:感谢您的回复 - 我认为最好的解决方案(或至少另一种选择)可能是一个匿名函数,如下所示:

for task := range ch {
  func () {
    ...
    if (...) {
      ...
      return
    }
    ...
  } ()
  worker.setIdle()
}

唯一的缺点是返回语句可能具有误导性,它们可能应该被评论。关于基本块粒度(或整个循环粒度)的“延迟”语句会很高兴:-)

标签: for-loopgo

解决方案


实现此目的的一种简单方法是将循环体提取到函数并像这样重组代码:

for task := range ch {
  doSomething(task)
  worker.setIdle()
}

func doSomething(task Task) {
   if (...) {
     ...
     return
   }
   if (...) {
     ...
     return
   }
   ...
}

这可能会导致更好地分离关注点:一个处理传入任务的函数和一个工作人员以及一个执行实际工作的函数。


推荐阅读