<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                合規國際互聯網加速 OSASE為企業客戶提供高速穩定SD-WAN國際加速解決方案。 廣告
                17-異常處理 =========== [Errors](#171-errors)<br/> [Throws](#172-throws)<br/> [Exits](#173-exits)<br/> [After](#174-after)<br/> [變量作用域](#175-%E5%8F%98%E9%87%8F%E4%BD%9C%E7%94%A8%E5%9F%9F)<br/> Elixir有三種錯誤處理機制:errors,throws和exits。本章我們將逐個講解它們,包括應該在何時使用哪一個。 ## 17.1-Errors 舉個例子,嘗試讓原子加上一個數字,就會激發一個錯誤(errors): ``` iex> :foo + 1 ** (ArithmeticError) bad argument in arithmetic expression :erlang.+(:foo, 1) ``` 使用宏```raise/1```可以在任何時候激發一個運行時錯誤: ``` iex> raise "oops" ** (RuntimeError) oops ``` 用```raise/2```,并且附上錯誤名稱和一個鍵值列表可以激發規定好的錯誤: ``` iex> raise ArgumentError, message: "invalid argument foo" ** (ArgumentError) invalid argument foo ``` 你可以使用```defexception/2```定義你自己的錯誤。最常見的是定義一個有消息說明的錯誤: ``` iex> defexception MyError, message: "default message" iex> raise MyError ** (MyError) default message iex> raise MyError, message: "custom message" ** (MyError) custom message ``` 用```try/catch```結構可以處理異常: ``` iex> try do ...> raise "oops" ...> rescue ...> e in RuntimeError -> e ...> end RuntimeError[message: "oops"] ``` 這個例子處理了一個運行時異常,返回該錯誤本身(會被顯示在IEx對話中)。 在實際操作中,Elixir程序員很少使用```try/rescue```結構。 例如,當文件打開失敗,很多編程語言會強制你去處理一個異常。而Elixir提供的```File.read/1```函數返回包含信息的元組,不管文件打開成功與否: ``` iex> File.read "hello" {:error, :enoent} iex> File.write "hello", "world" :ok iex> File.read "hello" {:ok, "world"} ``` 這個例子中沒有```try/rescue```。如果你想處理打開文件可能的不同結果,你可以使用case來匹配: ``` iex> case File.read "hello" do ...> {:ok, body} -> IO.puts "got ok" ...> {:error, body} -> IO.puts "got error" ...> end ``` 使用這個匹配處理,你可以自己決定要不要把問題拋出來。 這就是為什么Elixir不讓```File.read/1```等函數自己拋出異常。它把決定權留給程序員,讓他們尋找最合適的處理方法。 如果你真的期待文件存在(_打開文件時文件不存在_這確實是一個錯誤),你可以簡單地使用```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 ``` 換句話說,我們避免使用```try/rescue```是因為我們**不用錯誤處理來控制程序執行流程**。 在Elixir中,我們視錯誤為其字面意思:它們只不過是用來表示意外或異常的信息。 如果你真的希望改變執行過程,你可以使用```throws```。 ## 17.2-Throws 在Elixir中,你可以拋出(throw)一個值稍后處理。```throw```和```catch```就被保留著為了處理一些你拋出了值,但是不用```try/catch```就取不到的情況。 這些情況實際中很少出現,除非當一個庫的接口沒有提供合適的API等情況。 例如,假如枚舉模塊沒有提供任何API來尋找某范圍內第一個13的倍數: ``` iex> try do ...> Enum.each -50..50, fn(x) -> ...> if rem(x, 13) == 0, do: throw(x) ...> end ...> "Got nothing" ...> catch ...> x -> "Got #{x}" ...> end "Got -39" ``` 但是它提供了這樣的函數```Enum.find/2```: ``` iex> Enum.find -50..50, &(rem(&1, 13) == 0) -39 ``` ## 17.3-Exits 每段Elixir代碼都在進程中運行,進程與進程相互交流。當一個進程終止了,它會發出```exit```信號。 一個進程可以通過顯式地發出這個信號來終止: ``` iex> spawn_link fn -> exit(1) end #PID<0.56.0> ** (EXIT from #PID<0.56.0>) 1 ``` 上面的例子中,鏈接著的進程通過發送```exit```信號(帶有參數數字1)而終止。Elixir shell自動處理這個信息并把它們顯示在終端上。 exit還可以被```try/catch```塊捕獲處理: ``` iex> try do ...> exit "I am exiting" ...> catch ...> :exit, _ -> "not really" ...> end "not really" ``` 因為```try/catch```已經很少用了,用它們捕獲exit信號就更少見了。 exit信號是Erlang虛擬機提供的高容錯性的重要部分。進程通常都在*監督樹(supervision trees)*下運行。 監督樹本身也是進程,它們通過exit信號監督其它進程。然后通過某些策略決定是否重啟。 就是這種監督系統使得```try/catch```和```try/rescue```代碼塊很少用到。與其處理一個錯誤,不如讓它*快速失敗*。 因為在失敗后,監督樹會保證我們的程序將恢復到一個已知的初始狀態去。 ## 17.4-After 有時候有必要使用```try/after```來保證某資源在使用后被正確關閉或清除。 例如,我們打開一個文件,然后使用```try/after```來確保它在使用后被關閉: ``` iex> {:ok, file} = File.open "sample", [:utf8, :write] iex> try do ...> IO.write file, "olá" ...> raise "oops, something went wrong" ...> after ...> File.close(file) ...> end ** (RuntimeError) oops, something went wrong ``` ## 17.5-變量作用域 對于定義在```try/catch/rescue/after```代碼塊中的變量,切記不可讓它們泄露到外面去。這時因為```try```代碼塊有可能會失敗,而這些變量此時并沒有正常綁定數值: ``` iex> try do ...> from_try = true ...> after ...> from_after = true ...> end iex> from_try ** (RuntimeError) undefined function: from_try/0 iex> from_after ** (RuntimeError) undefined function: from_after/0 ``` 至此我們結束了對```try/catch/rescue```等知識的介紹。你會發現其實這些概念在實際的Elixir編程中不太常用。盡管的確有時也會用到。 是時候討論一些Elixir的概念,如列表速構(comprehensions)和魔法印(sigils)了。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看