Tr

Try/Rescue 属于 Elixir

1 个练习

关于 Try/Rescue

try .. rescue可以用来捕获并处理代码块中抛出的错误。

例如:

try do
  raise RuntimeError, "error"
rescue
  e in RuntimeError -> :error
end
  • 第 1 行,用try声明代码块。
  • 第 2 行,这里放置可能产生错误的函数调用,在本例中我们调用的是raise/1。
  • 第 4 行,在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 不会强行给[…]函数加上异常。相反,它让开发者自己选择最合适的处理方式。

通过 GitHub 编辑 该链接会在新窗口或标签页中打开

学习 Try/Rescue