在任何編程語言中,都需要異常處理來處理運行時錯誤,這樣才能保持應用程序的正常流。異常通常會中斷應用程序的正常流,這就是為什么我們需要在應用程序中使用異常處理的原因。
通常,當Erlang中發(fā)生異?;蝈e誤時,將顯示以下消息。
{"init terminating in do_boot", {undef,[{helloworld,start,[],[]}, {init,start_it,1,[]},{init,start_em,1,[]}]}}
故障轉(zhuǎn)儲將被寫入-
erl_crash.dump init terminating in do_boot ()
在Erlang中,有3種例外類型-
Error?調(diào)用將終止當前進程的執(zhí)行,并在捕獲到最后一個函數(shù)及其參數(shù)時包含堆棧跟蹤。這些是引發(fā)上述運行時錯誤的異常。erlang:error(Reason)
Exists ?有兩種Exists : 內(nèi)部退出和外部退出。內(nèi)部退出通過調(diào)用函數(shù) exit/1來觸發(fā),并使當前進程停止執(zhí)行。外部出口在 exit/2中被調(diào)用,并且與 Erlang 的并發(fā)方面中的多個進程有關。
Throw ?throw是一類異常,用于程序員可以處理的情況。與退出和錯誤相比,它們并沒有帶來任何“崩潰過程!”他們背后的意圖,而是他們控制的流量。當您在期望程序員處理拋出時使用拋出,通常最好在使用它們的模塊中記錄它們的使用。
try... catch 是一種計算表達式的方法,同時讓您處理成功的案例以及遇到的錯誤。
try-catch表達式的一般語法如下所示。
try Expression of SuccessfulPattern1 [Guards] -> Expression1; SuccessfulPattern2 [Guards] -> Expression2 catch TypeOfError:ExceptionPattern1 -> Expression3; TypeOfError:ExceptionPattern2 -> Expression4 end
在 try 和 of 之間的表達式被稱為是受保護的。這意味著該調(diào)用中發(fā)生的任何類型的異常都將被捕獲。在 try... 和 catch 之間的模式和表達式與 case... 的行為方式完全相同。
Finally,catch 部分——在這里,您可以為本章中看到的每種類型,用 error、 throw 或 exit 替換 TypeOfError。如果沒有提供類型,則假定拋出。
Error | 錯誤類型 |
---|---|
badarg | 參數(shù)的數(shù)據(jù)類型錯誤,或者格式不正確。 |
badarith | 算術表達式中的錯誤參數(shù)。 |
{badmatch,V} | 匹配表達式的求值失敗。值V不匹配。 |
function_clause | 評估函數(shù)調(diào)用時找不到匹配的函數(shù)子句。 |
{case_clause,V} | 計算case表達式時找不到匹配的分支。值V不匹配。 |
if_clause | 評估if表達式時,找不到真正的分支。 |
{try_clause,V} | 計算try表達式的節(jié)的時找不到匹配的分支。值V不匹配。 |
undef | 評估函數(shù)調(diào)用時找不到該函數(shù)。 |
{badfun,F} | 有趣的F出了點問題 |
{badarit,F} | 一個趣味被應用于錯誤數(shù)量的參數(shù)。F描述了其中的樂趣和爭論。 |
timeout_value | receive..after表達式中的超時值將計算為除整數(shù)或無窮大之外的其他值。 |
noproc | 嘗試鏈接到不存在的進程。 |
以下是如何使用這些異常以及如何進行處理的示例。
第一個函數(shù)生成所有可能的異常類型。
然后我們編寫一個包裝器函數(shù),在try…catch表達式中調(diào)用generate_exception。
-module(helloworld). -compile(export_all). generate_exception(1) -> a; generate_exception(2) -> throw(a); generate_exception(3) -> exit(a); generate_exception(4) -> {'EXIT', a}; generate_exception(5) -> erlang:error(a). demo1() -> [catcher(I) || I <- [1,2,3,4,5]]. catcher(N) -> try generate_exception(N) of Val -> {N, normal, Val} catch throw:X -> {N, caught, thrown, X}; exit:X -> {N, caught, exited, X}; error:X -> {N, caught, error, X} end. demo2() -> [{I, (catch generate_exception(I))} || I <- [1,2,3,4,5]]. demo3() -> try generate_exception(5) catch error:X -> {X, erlang:get_stacktrace()} end. lookup(N) -> case(N) of 1 -> {'EXIT', a}; 2 -> exit(a) end.
如果我們運行程序的HelloWorld::demo().,我們將獲得以下輸出
[{1,normal,a}, {2,caught,thrown,a}, {3,caught,exited,a}, {4,normal,{'EXIT',a}}, {5,caught,error,a}]