try .. rescue可以用来捕获并处理代码块中抛出的错误。
例如:
try do
raise RuntimeError, "error"
rescue
e in RuntimeError -> :error
end
try声明代码块。raise/1。rescue部分,我们对抛出错误的_模块_名进行模式匹配
->左侧:
e匹配到错误结构体。in是关键字。RuntimeError是要匹配的模块,但可以匹配任何错误模块,也可以用_匹配所有错误。以这种方式捕获的错误(有时也叫“异常”)是结构体。不同的错误结构体有不同的键。在标准库的“异常”部分中,可以找到所有预定义错误的列表。
# ArithmeticError caused by division by zero
%ArithmeticError{message: "bad argument in arithmetic expression"}
# Protocol.UndefinedError caused by passing `nil` to `Enum.count/1`
%Protocol.UndefinedError{description: "", protocol: Enumerable, value: nil}
在 Elixir 中,捕获错误的情况非常少见。通常,捕获到的错误会被记录到日志,或者发送给外部监控服务,然后再重新抛出。这意味着我们通常不关心某个具体错误结构体的内部结构。
异常概念介绍了如何定义自定义错误结构体。
避免使用错误来控制逻辑流程的编程模式。在 Elixir 中这是一种反模式。
# Avoid using errors for control-flow.
try do
{:ok, value} = MyModule.janky_function()
"All good! #{value}."
rescue
e in RuntimeError ->
reason = e.message
"Uh oh! #{reason}."
end
# Rather, use control-flow structures for control-flow.
case MyModule.janky_function() do
{:ok, value} -> "All good! #{value}."
{:error, reason} -> "Uh oh! #{reason}."
end
正如 Elixir 入门指南中所写:
在[执行某个操作]时发生的错误是否属于异常情况,由你的应用程序自行决定。正因如此,Elixir 不会强行给[…]函数加上异常。相反,它让开发者自己选择最合适的处理方式。