幾乎每個程式語言都有例外處理的功能,當程式在執行時,不免都會遇到非工程師預期的狀況發生,我們可以針對不同例外訊息設計不同的例外處理。
在Ruby例外處理的基本架構:
begin
#程式碼正常執行的地方 (可能出現例外的程式碼)
rescue
#發生錯誤時執行的地方
end
當Ruby執行程式發生錯誤時,會丟出一個Error類別產生的例外物件並停止程式,各種錯誤類型用架構的方式歸納:
圖片來源:Programming Ruby book
有這麼多例外訊息的類別,要舉例可能舉不完,不過用起來大概像下面這種感覺:
begin
# 可能出現例外的程式碼
rescue SyntaxError
# 出現SyntaxError時執行此行程式碼
rescue ArgumentError
# 出現ArgumentError時執行此行程式碼
rescue RuntimeError
# 出現RuntimeError時執行此行程式碼
end
所以可針對丟出的例外訊息,去處理該訊息的例外處理,當然最常見的還是SyntaxError
, ArgumentError
及RuntimeError
。如果沒有在rescue
後特別寫哪種類別的話,任何的錯誤類別都會被rescue
給抓到。
在舉例之前,我想先說說該如何用raise來產生例外處理。
一般在簡單的程式碼,比較不會有例外處理的狀況發生,但為了舉例,我們也可以透過手動產生例外處理來觸發我們想要的結果,那我們就可以用raise method來執行。
The raise method is from the Kernel module. By default, raise creates an exception of the RuntimeError class.
raise是來自於Kernel這個module的method,"預設"會產生來自RuntimeError這個類別的exception實體。
既然是預設,代表我們一定可以自己寫raise method後會產生哪個類別的實體。
def raise_exception
puts '這邊是執行到raise之前'
raise '發生錯誤!'
puts '這邊是執行到raise之後'
end
raise_exception
印出
這邊是執行到raise之前
Traceback (most recent call last):
1: from test.rb:18:in `<main>'
test.rb:15:in `raise_exception': 發生錯誤! (RuntimeError)
#預設類別
def raise_exception
puts '這邊是執行到raise之前'
raise ArgumentError, '發生錯誤!'
puts '這邊是執行到raise之後'
end
raise_exception
印出
這邊是執行到raise之前
Traceback (most recent call last):
1: from test.rb:18:in `<main>'
test.rb:15:in `raise_exception': 發生錯誤! (ArgumentError)
#被指定類別
程式執行時先印出"發生例外之前",之後遇到raise
發生例外,故去找rescue
底下的程式碼並執行,印出"已處理例外"。
def raise_exception
begin
puts '發生例外之前'
raise '發生例外!' #沒指定Error類別,預設為RuntimeError
puts '發生例外之後'
rescue #預設RuntimeError,所有錯誤都會到這執行
puts '已處理例外'
end
end
raise_exception
# => 發生例外之前
# 已處理例外
程式執行時先印出"發生例外之前",之後遇到raise
LoadError類別發生例外,因為已被指定是遇到LoadError產生的實體,rescue後並無指定要救援哪個類別,故印出"發生例外! (LoadError)"。
def raise_exception
begin
puts '發生例外之前'
raise LoadError, '發生例外!'
puts '發生例外之後'
rescue
puts '已處理例外'
end
end
raise_exception
# => 發生例外之前
# 發生例外! (LoadError)
若要修正,只要將rescue後加入該發生例外訊息時的類別就可以了。
def raise_exception
begin
puts '發生例外之前'
raise LoadError, '發生例外!'
puts '發生例外之後'
rescue LoadError
puts '已處理例外'
end
end
raise_exception
# => 發生例外之前
# 已處理例外
其實以上範例的begin
跟end
,可以被同時省略,只要留下rescue
就可以正常執行,讓程式碼看起來更精簡,但對於金魚腦的我來說,為了方便未來能夠容易閱(理)讀(解),還是不會把它們省略。
def raise_exception
puts '發生例外之前'
raise LoadError, '發生例外!'
puts '發生例外之後'
rescue LoadError
puts '已處理例外'
end
raise_exception
# => 發生例外之前
# 已處理例外
其實這個主題可以寫出非常多東西,目前只針對自己可能會用到的部分做說明,如果有興趣的朋友可以到參考資料看更多關於Exceptions的介紹。
begin...rescue...end
用來解決非預期的結果。
begin
end
可省略參考資料:
Ruby Kernel
Ruby Exceptions
例外處理 Rescue Exception, Error Handling, Custom Error Pages
[Ruby] Error Handling(錯誤處理)
Ruby 的例外處理機制
Rails的錯誤處理機制begin、rescue和Exception
“The meaning of life is to find your gift. The purpose >of life is to give it away.”
– Pablo Picasso, Artist
本文同步發佈於: https://louiswuyj.tw/