2011-06-03 23 views
9

考慮這個開始救援,確保塊:如果您運行的代碼,因爲它是Ruby沒有「確保」當我「重試」的「拯救」

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

,因爲它提出了一個異常沒有稱爲'make_service_call()'的函數。所以,它重試。但是它會陷入無限循環,因爲控制永遠不會因'重試'而'確保'。不應該'確保'塊的一部分,確保無論在'開始'或'救援'中發生什麼,它中的代碼都會被執行嗎?

當然,我可以在「開始」中增加計數 - 這不是重點。我只是問了一些關於「確保」的問題,以便弄清楚一些問題。離開begin聲明(通過任何方式),但是當你retry,你只是在聲明中移動,因此確保部分將不被執行時

回答

17

ensure部分被執行。

試試這個版本的例子中得到了什麼事情的一個更好的主意:

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

ensure代碼被執行一次,只是代碼塊退出之前,它在那個時候被調用。

但由於unless attempts>2條件,而事實上,ensure將只稱爲「代碼退出之前」(例如,由於exit -1)的attempts += 1將不被執行,並且因此是一個無限循環。

ensure就像是在C++ __finally:你可以catch異常,然後使用一個goto:但finally不會被調用,直到函數實際上是即將退出。