Lassen Sie uns sagen, dass wir folgende Berechnung implementieren möchten:Nesting-Funktion ruft in GO
outval/err = f3(f3(f1(inval))
wo jeder f1
, f2
, f3
kann zu diesem Zeitpunkt wir die Berechnung mit einem Fehler fehl stoppen und setzen err
auf Fehler, der von der fehlerhaften Funktion zurückgegeben wird. (Natürlich kann Verschachtelung beliebig lang sein)
In Sprachen wie C++/Java/C# kann es leicht, indem f1
erfolgen, f2
und f3
eine Ausnahme aus und umschließt die Berechnung in einem Try-Catch-Block, während in Sprachen wie Haskell können wir stattdessen Monaden verwenden.
Jetzt versuche ich es in GO zu implementieren und der einzige Ansatz, den ich mir vorstellen kann, ist offensichtlich, wenn - sonst Leiter, die ziemlich ausführlich ist. Ich habe kein Problem, wenn wir die Aufrufe nicht verschachteln können, aber meiner Meinung nach fügt das Hinzufügen einer Fehlerüberprüfung nach jeder Zeile im Code hässlich aus und es unterbricht den Fluss. Ich würde gerne wissen, ob es einen besseren Weg gibt, es zu tun.
Edit: Bearbeiten gemäß dem Kommentar von peterSO
Unter dem konkreten Beispiel ist und einfache Implementierung
package main
import "fmt"
func f1(in int) (out int, err error) {
return in + 1, err
}
func f2(in int) (out int, err error) {
return in + 2, err
}
func f3(in int) (out int, err error) {
return in + 3, err
}
func calc(in int) (out int, err error) {
var temp1, temp2 int
temp1, err = f1(in)
if err != nil {
return temp1, err
}
temp2, err = f2(temp1)
if err != nil {
return temp2, err
}
return f3(temp2)
}
func main() {
inval := 0
outval, err := calc3(inval)
fmt.Println(inval, outval, err)
}
Was ich versuche Funktion calc zu erläutern ist, hat einige Berechnung möglicherweise mit Hilfe von Bibliotheksfunktionen Dies kann fehlschlagen und die Semantik ist, wenn ein Aufruf fehlschlägt. calc leitet den Fehler an den Aufrufer weiter (ähnlich wie die Ausnahme nicht behandelt wird). Meiner Meinung nach ist code für calc hässlich.
Zwischen für diesen speziellen Fall, in dem alle Bibliotheksfunktionen exakt gleiche Signatur haben, können wir den Code besser machen (Ich verwende Idee von http://golang.org/doc/articles/wiki/#tmp_269)
func saferun(f func (int) (int, error)) func (int, error) (int, error) {
return func (in int, err error) (int, error) {
if err != nil {
return in, err
}
return f(in)
}
}
Dann können wir calc als
neu definierenfunc calc(in int) (out int, err error) {
return saferun(f3)(saferun(f2)(f1(in)))
}
oder als
func calc(in int) (out int, err error) {
sf2 := saferun(f2)
sf3 := saferun(f3)
return sf3(sf2(f1(in)))
}
Aber ohne Generika s Ich bin mir nicht sicher, wie ich diesen Ansatz für einen Satz von Bibliotheksfunktionen verwenden kann.
Danke für die Antwort, aber ich bin mir nicht sicher, ob ich Ihren Ansatz verstehe. Was passiert, wenn ich die Signatur von f1, f2, f3 etc. nicht kontrolliere, weil sie Bibliotheksfunktionen sind.In meiner bescheidenen Meinung erfordern Fehlerbehandlungsinfrastrukturen in anderen Sprachen nicht, dass Sie solch eine Kontrolle haben – Suyog
Suyog, zitierend von Ihrer ursprünglichen Frage, "... getan, indem f1, f2 und f3 eine Ausnahme werfen ..." Es sicher klingt wie du und erlaubst das Ändern von f1, f2 und f3, um Ausnahmen auszulösen. Panik zu haben ist nicht anders. Panik ist der in Go verfügbare Mechanismus, um den Stapel von beliebiger Tiefe abzuwickeln und dabei einen Wert zurückzugeben. Es ist nicht der idiomatische und bevorzugte Weg, Fehler in Go zu behandeln, aber es ist der Mechanismus, der das tut, was Sie fragen. – Sonia
Ich meinte, f1, f2, f3 sind bereits definiert, um eine Ausnahme zu werfen. Entschuldigung für schlechte Formulierungen. In einer Sprache wie JAVA sind viele Bibliotheksfunktionen so definiert, dass sie eine Ausnahme auslösen, während es in GO anscheinend so ist, dass Bibliotheksfunktionen einen Fehler zurückgeben. Das Problem, vor dem ich stehe, ist, dass ich Fehler sofort überprüfen muss, was dazu führt, dass sich repetitiver Code schreibt. – Suyog