当我”救援”重试’时,Ruby不会“确保”

考虑一下这个begin-rescue-ensure块:

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

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

当然,我可以在’开始’中递增计数 – 这不是重点。 我只想问一下’确保’的问题,以便澄清一下。

在离开begin语句时(通过任何方式)执行ensure部分,但是当你retry ,你只是在语句内移动,所以不会执行ensure部分。

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

 attempts = 0 begin make_service_call() rescue Exception attempts += 1 retry unless attempts > 2 exit -1 ensure puts "ensure! #{attempts}" end 

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

但是由于unless attempts>2条件,并且ensure将仅在“代码退出之前”被调用(例如,由于exit -1 ),因此将不会执行attempts += 1 ,因此存在无限环。

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