Elixir - Penanganan Kesalahan
Elixir memiliki tiga mekanisme kesalahan: kesalahan, lemparan dan keluar. Mari kita bahas setiap mekanisme secara mendetail.
Kesalahan
Kesalahan (atau pengecualian) digunakan saat hal-hal luar biasa terjadi dalam kode. Kesalahan sampel dapat diambil dengan mencoba menambahkan angka ke dalam string -
IO.puts(1 + "Hello")
Ketika program di atas dijalankan, itu menghasilkan kesalahan berikut -
** (ArithmeticError) bad argument in arithmetic expression
:erlang.+(1, "Hello")
Ini adalah contoh kesalahan bawaan.
Meningkatkan Kesalahan
Kita dapat raisekesalahan menggunakan fungsi kenaikan. Mari kita pertimbangkan contoh untuk memahami hal yang sama -
#Runtime Error with just a message
raise "oops" # ** (RuntimeError) oops
Kesalahan lain dapat dimunculkan dengan menaikkan / 2 melewati nama kesalahan dan daftar argumen kata kunci
#Other error type with a message
raise ArgumentError, message: "invalid argument foo"
Anda juga dapat menentukan kesalahan Anda sendiri dan meningkatkannya. Perhatikan contoh berikut -
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
Kesalahan Penyelamatan
Kami tidak ingin program kami berhenti secara tiba-tiba, tetapi kesalahan harus ditangani dengan hati-hati. Untuk ini kami menggunakan penanganan kesalahan. Kitarescue kesalahan menggunakan try/rescuemembangun. Mari kita pertimbangkan contoh berikut untuk memahami hal yang sama -
err = try do
raise "oops"
rescue
e in RuntimeError -> e
end
IO.puts(err.message)
Ketika program di atas dijalankan, menghasilkan hasil sebagai berikut -
oops
Kami telah menangani kesalahan dalam pernyataan penyelamatan menggunakan pencocokan pola. Jika kami tidak memiliki penggunaan kesalahan, dan hanya ingin menggunakannya untuk tujuan identifikasi, kami juga dapat menggunakan formulir -
err = try do
1 + "Hello"
rescue
RuntimeError -> "You've got a runtime error!"
ArithmeticError -> "You've got a Argument error!"
end
IO.puts(err)
Saat menjalankan program di atas, ini menghasilkan hasil sebagai berikut -
You've got a Argument error!
NOTE- Sebagian besar fungsi di pustaka standar Elixir diimplementasikan dua kali, sekali mengembalikan tupel dan waktu lainnya meningkatkan kesalahan. Misalnya, fileFile.read dan File.read!fungsi. Yang pertama mengembalikan tupel jika file berhasil dibaca dan jika terjadi kesalahan, tupel ini digunakan untuk memberikan alasan kesalahan. Yang kedua memunculkan kesalahan jika terjadi kesalahan.
Jika kita menggunakan pendekatan fungsi pertama, maka kita perlu menggunakan kasus untuk pola yang cocok dengan kesalahan dan mengambil tindakan sesuai dengan itu. Dalam kasus kedua, kami menggunakan pendekatan coba penyelamatan untuk kode rawan kesalahan dan menangani kesalahan yang sesuai.
Melempar
Di Elixir, sebuah nilai bisa dilempar dan kemudian ditangkap. Throw dan Catch disediakan untuk situasi di mana tidak mungkin mengambil nilai kecuali dengan menggunakan lemparan dan tangkap.
Instance ini tidak umum dalam praktiknya kecuali saat berinteraksi dengan library. Misalnya, sekarang mari kita asumsikan bahwa modul Enum tidak menyediakan API apa pun untuk menemukan nilai dan bahwa kita perlu menemukan kelipatan pertama dari 13 dalam daftar angka -
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)
Ketika program di atas dijalankan, menghasilkan hasil sebagai berikut -
Got 26
Keluar
Ketika suatu proses mati karena "penyebab alami" (misalnya, pengecualian yang tidak tertangani), ia mengirimkan sinyal keluar. Suatu proses juga bisa mati dengan mengirimkan sinyal keluar secara eksplisit. Mari kita perhatikan contoh berikut -
spawn_link fn -> exit(1) end
Pada contoh di atas, proses yang terhubung mati dengan mengirimkan sinyal keluar dengan nilai 1. Perhatikan bahwa keluar juga bisa “ditangkap” menggunakan coba / tangkap. Misalnya -
val = try do
exit "I am exiting"
catch
:exit, _ -> "not really"
end
IO.puts(val)
Ketika program di atas dijalankan, menghasilkan hasil sebagai berikut -
not really
Setelah
Terkadang perlu untuk memastikan bahwa sumber daya dibersihkan setelah beberapa tindakan yang berpotensi menimbulkan kesalahan. Konstruksi coba / setelah memungkinkan Anda melakukan itu. Misalnya, kita dapat membuka file dan menggunakan klausa setelah untuk menutupnya – bahkan jika terjadi kesalahan.
{:ok, file} = File.open "sample", [:utf8, :write]
try do
IO.write file, "olá"
raise "oops, something went wrong"
after
File.close(file)
end
Ketika kami menjalankan program ini, itu akan memberi kami kesalahan. Tetapiafter pernyataan akan memastikan bahwa deskriptor file ditutup saat kejadian seperti itu.