📅  最后修改于: 2020-11-04 05:34:48             🧑  作者: Mango
Elixir具有三种错误机制:错误,抛出和退出。让我们详细探讨每种机制。
当代码中发生异常情况时,将使用错误(或异常)。可以通过尝试将数字添加到字符串来检索示例错误-
IO.puts(1 + "Hello")
当上述程序运行时,会产生以下错误-
** (ArithmeticError) bad argument in arithmetic expression
:erlang.+(1, "Hello")
这是一个示例内置错误。
我们可以使用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!
注– Elixir标准库中的大多数函数实现两次,一次返回元组,另一次则引发错误。例如, File.read和File.read!功能。如果成功读取文件,并且遇到错误,则第一个返回一个元组,该元组用于提供错误原因。如果遇到错误,第二个错误将引发错误。
如果我们使用第一个函数方法,那么我们需要使用用例来对错误进行模式匹配,并据此采取措施。在第二种情况下,我们对容易出错的代码使用try try方法,并相应地处理错误。
在Elixir中,可以引发一个值,以后再捕获它。 Throw和Catch保留用于除非使用throw and 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
当进程死于“自然原因”(例如,未处理的异常)时,它将发送退出信号。通过显式发送退出信号,进程也可以终止。让我们考虑以下示例-
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
有时有必要确保在执行可能会引发错误的操作后清理资源。 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语句将确保在任何此类事件时文件描述符都被关闭。