- Elixir 教程
- Elixir - 首頁
- Elixir - 概述
- Elixir - 環境
- Elixir - 基本語法
- Elixir - 資料型別
- Elixir - 變數
- Elixir - 運算子
- Elixir - 模式匹配
- Elixir - 決策
- Elixir - 字串
- Elixir - 字元列表
- Elixir - 列表和元組
- Elixir - 關鍵字列表
- Elixir - 對映
- Elixir - 模組
- Elixir - 別名
- Elixir - 函式
- Elixir - 遞迴
- Elixir - 迴圈
- Elixir - 可列舉
- Elixir - 流
- Elixir - 結構體
- Elixir - 協議
- Elixir - 檔案 I/O
- Elixir - 程序
- Elixir - 符號
- Elixir - 推導式
- Elixir - 型別規範
- Elixir - 行為
- Elixir - 錯誤處理
- Elixir - 宏
- Elixir - 庫
- Elixir 有用資源
- Elixir - 快速指南
- Elixir - 有用資源
- Elixir - 討論
Elixir - 錯誤處理
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
我們在 `rescue` 語句中使用模式匹配處理了錯誤。如果我們沒有使用錯誤,只是想將其用於識別目的,我們也可以使用以下形式:
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!` 函式。如果檔案讀取成功,第一個函式將返回一個元組;如果遇到錯誤,則使用此元組來提供錯誤原因。第二個函式如果遇到錯誤則引發錯誤。
如果我們使用第一種函式方法,則需要使用 `case` 來匹配錯誤模式並根據該模式採取行動。在第二種情況下,我們對容易出錯的程式碼使用 `try rescue` 方法並相應地處理錯誤。
丟擲
在 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
退出
當程序因“自然原因”(例如未處理的異常)死亡時,它會發送一個退出訊號。程序也可以透過顯式傳送退出訊號來死亡。讓我們考慮以下示例:
spawn_link fn -> exit(1) end
在上面的示例中,連結的程序透過傳送值為 1 的退出訊號死亡。請注意,`exit` 也可以使用 `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` 語句將確保在任何此類事件發生時關閉檔案描述符。