重试时为什么不调用ensure子句?

时间:2012-12-01 09:55:04

标签: ruby exception-handling

这是一个片段

def take_resource
  puts "resource taken"
end

def free_resource source
  puts "resource freed from #{source}"
end

def do_stuff
  tries = 0
  begin
    take_resource
    raise 'oops'
  rescue
    if tries < 3
      tries += 1
      free_resource 'rescue'
      retry
    end
    raise
  ensure
    free_resource 'ensure'
  end
end


do_stuff

# ~> -:13:in `do_stuff': oops (RuntimeError)
# ~>    from -:28:in `<main>'
# >> resource taken
# >> resource freed from rescue
# >> resource taken
# >> resource freed from rescue
# >> resource taken
# >> resource freed from rescue
# >> resource taken
# >> resource freed from ensure

在这里,我们看到当ensure块时,不会调用retry子句。这是为什么?对此有合理的解释吗?我认为ensure被称为ensure有一个原因:它总是运行。好吧,事实证明我错了。

虽然我们正在谈论它:你知道这方面的其他陷阱(异常处理)吗?

1 个答案:

答案 0 :(得分:1)

无论是通过异常还是正常退出块,都会调用

ensureretry只是将执行点转移到块的开头,因此您仍然在块中,并且不会调用ensure

考虑存在ensure以帮助在退出块时清理资源。如果你还在街区,那么大概你还在使用这些资源。

这是预期的行为。

这些关键字在编程Ruby书(http://www.ruby-doc.org/docs/ProgrammingRuby/html/tut_exceptions.html

中有详细描述