Elixir 錯(cuò)誤

2023-12-16 20:47 更新

錯(cuò)誤(或 異常 )用于代碼中發(fā)生異常時(shí).當(dāng)試圖將一個(gè)數(shù)字與原子相加,就可得到一個(gè)錯(cuò)誤的例子:

iex> :foo + 1
** (ArithmeticError) bad argument in arithmetic expression
     :erlang.+(:foo, 1)

一個(gè)運(yùn)行時(shí)錯(cuò)誤可有?raise/1?引發(fā):

iex> raise "oops"
** (RuntimeError) oops

其它錯(cuò)誤可以由?raise/2?引發(fā),通過(guò)傳送錯(cuò)誤名稱和一個(gè)關(guān)鍵詞列表作為參數(shù):

iex> raise ArgumentError, message: "invalid argument foo"
** (ArgumentError) invalid argument foo

你也可以通過(guò)在一個(gè)模塊中使用?defexception?結(jié)構(gòu)來(lái)定義你自己的錯(cuò)誤;這時(shí)你創(chuàng)造了一個(gè)與模塊同名的錯(cuò)誤.最常用的場(chǎng)景是定義一個(gè)帶信息場(chǎng)的異常:

iex> defmodule MyError do
iex>   defexception message: "default message"
iex> end
iex> raise MyError
** (MyError) default message
iex> raise MyError, message: "custom message"
** (MyError) custom message

錯(cuò)誤可以被解救,通過(guò)try/rescue結(jié)構(gòu):

iex> try do
...>   raise "oops"
...> rescue
...>   e in RuntimeError -> e
...> end
%RuntimeError{message: "oops"}

上述例子將運(yùn)行時(shí)錯(cuò)誤解救,并返回錯(cuò)誤本身,然后將其打印到?iex?中.

如果錯(cuò)誤對(duì)你毫無(wú)用處,你可以不顯示它:

iex> try do
...>   raise "oops"
...> rescue
...>   RuntimeError -> "Error!"
...> end
"Error!"

實(shí)際中,Elixir開(kāi)發(fā)者很少用到try/rescue結(jié)構(gòu).例如,當(dāng)文件無(wú)法被打開(kāi)時(shí),許多語(yǔ)言會(huì)強(qiáng)制你解救這個(gè)錯(cuò)誤.作為替代,Elixir中提供了File.read/1函數(shù),其會(huì)返回一個(gè)包含文件是否被成功打開(kāi)的信息的元組.

iex> File.read "hello"
{:error, :enoent}
iex> File.write "hello", "world"
:ok
iex> File.read "hello"
{:ok, "world"}

這里沒(méi)有try/rescue.如果你想要處理打開(kāi)文件時(shí)的不同輸出,你可以簡(jiǎn)單地使用case來(lái)進(jìn)行模式匹配:

iex> case File.read "hello" do
...>   {:ok, body}      -> IO.puts "Success: #{body}"
...>   {:error, reason} -> IO.puts "Error: #{reason}"
...> end

最終,打開(kāi)文件時(shí)發(fā)生的錯(cuò)誤是否為異常將由你的應(yīng)用來(lái)決定.這就是Elixir為何不給File.read/1和其它許多函數(shù)強(qiáng)加異常.而是留給開(kāi)發(fā)者來(lái)選擇最好的處理方式.

當(dāng)你確信一個(gè)文件存在(缺失文件確實(shí)是錯(cuò)誤的),你可以簡(jiǎn)單地使用File.read!/1:

iex> File.read! "unknown"
** (File.Error) could not read file unknown: no such file or directory
    (elixir) lib/file.ex:305: File.read!/1

標(biāo)準(zhǔn)庫(kù)中的許多函數(shù)遵循對(duì)應(yīng)的異常引發(fā)模式,而非返回匹配元組.函數(shù)foo會(huì)返回{:ok, result}{:error, reason}元組,而另一個(gè)函數(shù)(foo!,同名但帶有!)雖然接受與foo同樣的參數(shù),但遇到錯(cuò)誤時(shí)會(huì)拋出異常.如果一切正常,foo!會(huì)返回(沒(méi)有被元組包裹的)結(jié)果.File模塊就是很好的例子.

在Elixir中,我們避免使用try/rescue,因?yàn)?strong>我們不在控制流中使用錯(cuò)誤.我們這樣解釋錯(cuò)誤:它們是預(yù)留給意料外或異常的情形的.當(dāng)你需要使用控制流結(jié)構(gòu)時(shí),應(yīng)該使用拋出.下面我們將講到.


以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)