- Erlang 教程
- Erlang - 首页
- Erlang - 概述
- Erlang - 环境
- Erlang - 基本语法
- Erlang - Shell
- Erlang - 数据类型
- Erlang - 变量
- Erlang - 运算符
- Erlang - 循环
- Erlang - 决策
- Erlang - 函数
- Erlang - 模块
- Erlang - 递归
- Erlang - 数字
- Erlang - 字符串
- Erlang - 列表
- Erlang - 文件 I/O
- Erlang - 原子
- Erlang - 映射
- Erlang - 元组
- Erlang - 记录
- Erlang - 异常
- Erlang - 宏
- Erlang - 头文件
- Erlang - 预处理器
- Erlang - 模式匹配
- Erlang - 守护进程
- Erlang - BIFS
- Erlang - 二进制
- Erlang - 函数
- Erlang - 进程
- Erlang - 邮件
- Erlang - 数据库
- Erlang - 端口
- Erlang - 分布式编程
- Erlang - OTP
- Erlang - 并发
- Erlang - 性能
- Erlang - 驱动程序
- Erlang - Web 编程
- Erlang 有用资源
- Erlang - 快速指南
- Erlang - 有用资源
- Erlang - 讨论
Erlang - 异常
异常处理在任何编程语言中都是必需的,用于处理运行时错误,以便维护应用程序的正常流程。异常通常会中断应用程序的正常流程,这就是为什么我们需要在应用程序中使用异常处理的原因。
通常,当 Erlang 中发生异常或错误时,将显示以下消息。
{"init terminating in do_boot", {undef,[{helloworld,start,[],[]}, {init,start_it,1,[]},{init,start_em,1,[]}]}}
崩溃转储将写入 -
erl_crash.dump init terminating in do_boot ()
在 Erlang 中,有三种类型的异常 -
错误 - 调用 erlang:error(Reason) 将终止当前进程中的执行,并在您捕获它时包含最后调用的函数及其参数的堆栈跟踪。这些是导致上面运行时错误的异常类型。
退出 - 有两种类型的退出:'内部'退出和'外部'退出。内部退出是通过调用函数 exit/1 触发的,并使当前进程停止执行。外部退出使用 exit/2 调用,并且与 Erlang 并发方面的多个进程有关。
抛出 - 抛出是一类异常,用于程序员可以预期处理的情况。与退出和错误相比,它们并没有真正带有任何“崩溃该进程!”的意图,而是控制流程。当您在预期程序员处理抛出时使用它们时,通常最好使用它们记录模块中的用法。
try ... catch 是一种评估表达式的 方法,同时允许您处理成功的情况以及遇到的错误。
try catch 表达式的通用语法如下。
语法
try Expression of SuccessfulPattern1 [Guards] -> Expression1; SuccessfulPattern2 [Guards] -> Expression2 catch TypeOfError:ExceptionPattern1 -> Expression3; TypeOfError:ExceptionPattern2 -> Expression4 end
try 和 of 之间的表达式被称为受保护的。这意味着在该调用中发生的任何类型的异常都将被捕获。try ... of 和 catch 之间的模式和表达式与 case ... of 的行为完全相同。
最后,是 catch 部分 - 在这里,您可以将 TypeOfError 替换为 error、throw 或 exit,分别对应我们本章中看到的每种类型。如果未提供类型,则假定为 throw。
以下是 Erlang 中的一些错误和错误原因 -
错误 | 错误类型 |
---|---|
badarg | 错误的参数。参数的数据类型错误,或者格式错误。 |
badarith | 算术表达式中的错误参数。 |
{badmatch,V} | 匹配表达式的评估失败。值 V 没有匹配。 |
function_clause | 在评估函数调用时找不到匹配的函数子句。 |
{case_clause,V} | 在评估 case 表达式时找不到匹配的分支。值 V 没有匹配。 |
if_clause | 在评估 if 表达式时找不到 true 分支。 |
{try_clause,V} | 在评估 try 表达式的 of 部分时找不到匹配的分支。值 V 没有匹配。 |
undef | 在评估函数调用时找不到函数。 |
{badfun,F} | 函数 F 有问题 |
{badarity,F} | 函数应用于错误数量的参数。F 描述了函数和参数。 |
timeout_value | receive..after 表达式中的超时值计算结果不是整数或无限大。 |
noproc | 尝试链接到不存在的进程。 |
下面是一个关于如何使用这些异常以及如何执行操作的示例。
第一个函数生成所有可能的异常类型。
然后我们编写一个包装器函数,在 try...catch 表达式中调用 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}]