返回介绍

错误处理( Errors Handling)

发布于 2021-05-25 13:29:46 字数 2939 浏览 1085 评论 0 收藏 0

Elixir有三种错误机制:错误,抛出和退出。 让我们详细探讨每种机制。

Error

当代码中发生异常事件时,将使用错误(或异常)。 尝试将数字添加到字符串中可以检索样本错误 -

IO.puts(1 + "Hello")

运行上述程序时,会产生以下错误 -

** (ArithmeticError) bad argument in arithmetic expression
   :erlang.+(1, "Hello")

这是一个内置错误示例。

提高错误

我们可以使用raise函数raise错误。 让我们考虑一个例子来理解相同的 -

#Runtime Error with just a message
raise "oops"  # ** (RuntimeError) oops

通过raise/2传递错误名称和关键字参数列表,可以引发其他错误

#Other error type with a message
raise ArgumentError, message: "invalid argument foo"

您还可以定义自己的错误并提高它们。 考虑以下示例 -

defmodule MyError do
   defexception message: "default message"
end
raise MyError  # Raises error with default message
raise MyError, message: "custom message"  # Raises error with custom message

拯救错误

我们不希望我们的程序突然退出,而是需要仔细处理错误。 为此,我们使用错误处理。 我们使用try/rescue构造来挽救错误。 让我们考虑下面的例子来理解相同的 -

err = try do
   raise "oops"
rescue
   e in RuntimeError -> e
end
IO.puts(err.message)

运行上述程序时,会产生以下结果 -

oops

我们使用模式匹配处理了救援声明中的错误。 如果我们没有使用任何错误,并且只想将其用于识别目的,我们也可以使用表格 -

err = try do
   1 + "Hello"
rescue
   RuntimeError -> "You've got a runtime error!"
   ArithmeticError -> "You've got a Argument error!"
end
IO.puts(err)

在程序上运行时,会产生以下结果 -

You've got a Argument error!

NOTE - Elixir标准库中的大多数函数都实现了两次,一次返回元组,另一次引发错误。 例如,File.read和File.read! 功能。 如果文件被成功读取,则第一个返回元组,如果遇到错误,则使用此元组给出错误的原因。 如果遇到错误,第二个引发错误。

如果我们使用第一个函数方法,那么我们需要使用case匹配错误的模式并根据它采取行动。 在第二种情况下,我们使用try rescue方法来处理容易出错的代码并相应地处理错误。

Throws

在Elixir中,可以抛出一个值,然后被捕获。 Throw和Catch保留用于无法检索值的情况,除非使用throw和catch。

除了与库连接外,实例在实践中非常罕见。 例如,现在让我们假设Enum模块没有提供任何用于查找值的API,我们需要在数字列表中找到13的第一个倍数 -

val = try do
   Enum.each 20..100, fn(x) ->
      if rem(x, 13) == 0, do: throw(x)
   end
   "Got nothing"
catch
   x -> "Got #{x}"
end
IO.puts(val)

运行上述程序时,会产生以下结果 -

Got 26

退出 (Exit)

当一个进程死于“自然原因”(例如,未处理的异常)时,它会发送一个退出信号。 过程也可以通过显式发送退出信号而死亡。 让我们考虑以下示例 -

spawn_link fn -> exit(1) end

在上面的示例中,链接进程通过发送值为1的退出信号而死亡。请注意,退出也可以使用try/catch“捕获”。 例如 -

val = try do
   exit "I am exiting"
catch
   :exit, _ -> "not really"
end
IO.puts(val)

运行上述程序时,会产生以下结果 -

not really

After

有时需要确保在某些可能引发错误的操作之后清理资源。 try/after结构允许您这样做。 例如,我们可以打开一个文件并使用after子句来关闭它 - 即使出现问题。

{:ok, file} = File.open "sample", [:utf8, :write]
try do
   IO.write file, "olá"
   raise "oops, something went wrong"
after
   File.close(file)
end

当我们运行这个程序时,它会给我们一个错误。 但是after语句将确保在任何此类事件时关闭文件描述符。

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文