Elixier - Fehlerbehandlung
Elixir hat drei Fehlermechanismen: Fehler, Würfe und Exits. Lassen Sie uns jeden Mechanismus im Detail untersuchen.
Error
Fehler (oder Ausnahmen) werden verwendet, wenn außergewöhnliche Dinge im Code passieren. Ein Beispielfehler kann abgerufen werden, indem versucht wird, einer Zeichenfolge eine Zahl hinzuzufügen.
IO.puts(1 + "Hello")
Wenn das obige Programm ausgeführt wird, wird der folgende Fehler ausgegeben:
** (ArithmeticError) bad argument in arithmetic expression
:erlang.+(1, "Hello")
Dies war ein eingebauter Beispielfehler.
Fehler auslösen
Wir können raiseFehler bei der Verwendung der Erhöhungsfunktionen. Betrachten wir ein Beispiel, um dasselbe zu verstehen -
#Runtime Error with just a message
raise "oops" # ** (RuntimeError) oops
Andere Fehler können ausgelöst werden, indem Raise / 2 den Fehlernamen und eine Liste von Schlüsselwortargumenten übergibt
#Other error type with a message
raise ArgumentError, message: "invalid argument foo"
Sie können auch Ihre eigenen Fehler definieren und diese auslösen. Betrachten Sie das folgende Beispiel -
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
Fehler beheben
Wir möchten nicht, dass unsere Programme abrupt beendet werden, sondern dass die Fehler sorgfältig behandelt werden. Hierfür verwenden wir die Fehlerbehandlung. Wirrescue Fehler bei der Verwendung der try/rescuebauen. Betrachten wir das folgende Beispiel, um dasselbe zu verstehen:
err = try do
raise "oops"
rescue
e in RuntimeError -> e
end
IO.puts(err.message)
Wenn das obige Programm ausgeführt wird, wird das folgende Ergebnis erzeugt:
oops
Wir haben Fehler in der Rettungsanweisung mithilfe des Mustervergleichs behandelt. Wenn wir den Fehler nicht verwenden und ihn nur zu Identifikationszwecken verwenden möchten, können wir auch das Formular verwenden -
err = try do
1 + "Hello"
rescue
RuntimeError -> "You've got a runtime error!"
ArithmeticError -> "You've got a Argument error!"
end
IO.puts(err)
Wenn das obige Programm ausgeführt wird, wird das folgende Ergebnis angezeigt:
You've got a Argument error!
NOTE- Die meisten Funktionen in der Elixir-Standardbibliothek werden zweimal implementiert, wobei einmal Tupel zurückgegeben werden und das andere Mal Fehler auftreten. Zum Beispiel dieFile.read und die File.read!Funktionen. Das erste hat ein Tupel zurückgegeben, wenn die Datei erfolgreich gelesen wurde und ein Fehler aufgetreten ist. Dieses Tupel wurde verwendet, um den Grund für den Fehler anzugeben. Der zweite hat einen Fehler ausgelöst, wenn ein Fehler aufgetreten ist.
Wenn wir den ersten Funktionsansatz verwenden, müssen wir case für die Musterübereinstimmung mit dem Fehler verwenden und entsprechend handeln. Im zweiten Fall verwenden wir den Try-Rescue-Ansatz für fehleranfälligen Code und behandeln Fehler entsprechend.
Würfe
In Elixir kann ein Wert geworfen und später abgefangen werden. Wurf und Fang sind für Situationen reserviert, in denen es nicht möglich ist, einen Wert abzurufen, es sei denn, Sie verwenden Wurf und Fang.
Die Instanzen sind in der Praxis eher ungewöhnlich, außer wenn sie mit Bibliotheken verbunden sind. Nehmen wir nun zum Beispiel an, dass das Enum-Modul keine API zum Suchen eines Werts bereitgestellt hat und dass wir das erste Vielfache von 13 in einer Liste von Zahlen finden mussten -
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)
Wenn das obige Programm ausgeführt wird, wird das folgende Ergebnis erzeugt:
Got 26
Ausgang
Wenn ein Prozess an „natürlichen Ursachen“ stirbt (z. B. nicht behandelte Ausnahmen), sendet er ein Ausgangssignal. Ein Prozess kann auch durch explizites Senden eines Ausgangssignals sterben. Betrachten wir das folgende Beispiel:
spawn_link fn -> exit(1) end
Im obigen Beispiel wurde der verknüpfte Prozess durch Senden eines Exit-Signals mit dem Wert 1 beendet. Beachten Sie, dass der Exit auch mit try / catch „abgefangen“ werden kann. Zum Beispiel -
val = try do
exit "I am exiting"
catch
:exit, _ -> "not really"
end
IO.puts(val)
Wenn das obige Programm ausgeführt wird, wird das folgende Ergebnis erzeugt:
not really
Nach
Manchmal muss sichergestellt werden, dass eine Ressource nach einer Aktion bereinigt wird, die möglicherweise einen Fehler auslösen kann. Mit dem try / after-Konstrukt können Sie dies tun. Zum Beispiel können wir eine Datei öffnen und sie mit einer after-Klausel schließen - auch wenn etwas schief geht.
{:ok, file} = File.open "sample", [:utf8, :write]
try do
IO.write file, "olá"
raise "oops, something went wrong"
after
File.close(file)
end
Wenn wir dieses Programm ausführen, wird es uns einen Fehler geben. Aber dieafter Die Anweisung stellt sicher, dass der Dateideskriptor bei einem solchen Ereignis geschlossen wird.