考虑这个begin-rescue-ensure块:
attempts=0
begin
make_service_call()
rescue Exception
retry unless attempts>2
exit -1
ensure
attemps += 1
end
如果按原样运行该代码,则会引发异常,因为没有名为'make_service_call()'的函数。所以,它重试了。但它会陷入无限循环,因为控件永远不会因为“重试”而“确保”。不应该'确保'块的一部分确保其中的代码无论在'begin'或'rescue'中发生什么都会被执行?
当然我可以在'开始'中增加计数 - 这不是重点。我只是问'确保'这个问题,以便明确一些。
答案 0 :(得分:18)
ensure
部分在离开begin
语句时执行(无论如何)但是当你retry
时,你只是在声明中移动,所以确保部分不会被执行。
尝试使用此版本的示例,以便更好地了解正在发生的事情:
attempts = 0
begin
make_service_call()
rescue Exception
attempts += 1
retry unless attempts > 2
exit -1
ensure
puts "ensure! #{attempts}"
end
答案 1 :(得分:3)
ensure
代码执行一次,就在代码块退出之前,将在那时被调用。
但是由于unless attempts>2
条件,以及ensure
只会在“代码退出之前”被调用的事实(例如由于exit -1
)attempts += 1
将不会执行,因此存在无限循环。
ensure
与C ++中的__finally
类似:您可以catch
例外,然后使用goto
:但finally
将不会被调用,直到该函数实际上即将退出。