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