Phi*_*sky 6 error-handling erlang exception-handling
我正在Erlang中编写REST服务,需要先验证接收到的数据,然后再将其传递给其他内部函数进行进一步处理; 为了做到这一点,我目前正在使用这样的嵌套case表达式:
case all_args_defined(Args) of
true ->
ActionSuccess = action(Args),
case ActionSuccess of
{ok, _} -> ...;
{fail, reason} -> {fail, reason}
end,
_ ->
{fail, "args not defined"}
end,
...
Run Code Online (Sandbox Code Playgroud)
我意识到这有点难看,但这样我可以提供详细的错误信息.另外,我不认为通常的make it crash理念在这里适用 - 我不希望我的REST服务崩溃并且每当有人抛出无效参数时重新启动它.
但是,我正在考虑放弃所有那些cases支持伞形try/catch块来捕捉任何badmatch错误的人 - 这会有用吗?
fun() ->
true = all_args_defined(Args),
{ok, _} = action(Args).
%% somewhere else
catch fun().
Run Code Online (Sandbox Code Playgroud)
由于您要实现的是错误报告,因此您应该围绕执行操作和报告结果来构建事物.也许是这样的:
execute(Action, Args) ->
try
check_args(Args),
Result = action(Action, Args),
send_result(Result)
catch
throw:{fail, Reason} ->
report_error(Reason);
ExceptionClass:Term ->
%% catch-all for all other unexpected exceptions
Trace = erlang:get_stacktrace(),
report_error({crash, ExceptionClass, Term, Trace})
end.
%% all of these throw {fail, Reason} if they detect something fishy
%% and otherwise they return some value as result (or just crash)
action(foo, [X1, X2]) -> ...;
action(foo, Args) -> throw({fail, {bad_arity, foo, 2, Args}});
action(...) -> ...
%% this handles the formatting of all possible errors
report_error({bad_arity, Action, Arity, Args}) ->
send_error(io_lib:format("wrong number of arguments for ~w: "
"expected ~w, but got ~w",
[Action, Arity, length(Args)]));
report_error(...) -> ...;
report_error({crash, Class, Term, Trace}) ->
send_error(io_lib:format("internal error: "
"~w:~w~nstacktrace:~n~p~n",
[Class, Term, Trace])).
Run Code Online (Sandbox Code Playgroud)