10

考虑这个 begin-rescue-ensure 块:

attempts=0
begin
  make_service_call()
rescue Exception
  retry unless attempts>2
  exit -1
ensure
  attemps += 1
end

如果您按原样运行该代码,则会引发异常,因为没有名为“make_service_call()”的函数。所以,它重试。但它会陷入无限循环,因为控制永远不会因为“重试”而进入“确保”。无论“开始”或“救援”中发生什么,不应该“确保”块的一部分确保其中的代码被执行吗?

当然,我可以在“开始”中增加计数——这不是重点。我只是在问关于“确保”的问题,以便弄清楚。

4

2 回答 2

18

离开语句时(以任何方式)执行该ensure部分,但是当您 时,您只是在语句内移动,因此不会执行确保部分。beginretry

试试这个版本的示例,以更好地了解正在发生的事情:

attempts = 0
begin
  make_service_call()
rescue Exception
  attempts += 1
  retry unless attempts > 2
  exit -1
ensure
  puts "ensure! #{attempts}"
end
于 2011-06-03T06:12:12.050 回答
3

ensure代码执行一次,就在代码块退出之前,它将那时被调用。

但是由于条件,以及只会在“代码退出之前”被调用unless attempts>2的事实(例如由于),不会执行,因此存在无限循环。ensureexit -1attempts += 1

ensure就像__finally在 C++ 中一样:您可以catch使用异常然后使用goto: 但finally在函数实际上即将退出之前不会被调用。

于 2011-06-03T06:13:11.963 回答