Gehen die Verkettung von Methoden und Fehlerbehandlung
Ich möchte eine Methode erstellen, die die Verkettung API Gehen. In allen Beispielen, die ich finden kann die verkettete Vorgänge scheinen immer erfolgreich zu sein, das kann ich nicht garantieren. Deshalb will ich versuchen zu erweitern, zum hinzufügen von Fehler-Rückgabewert.
Wenn ich es so mache
package main
import "fmt"
type Chain struct {
}
func (v *Chain)funA() (*Chain, error ) {
fmt.Println("A")
return v, nil
}
func (v *Chain)funB() (*Chain, error) {
fmt.Println("B")
return v, nil
}
func (v *Chain)funC() (*Chain, error) {
fmt.Println("C")
return v, nil
}
func main() {
fmt.Println("Hello, playground")
c := Chain{}
d, err := c.funA().funB().funC() //line 24
}
Der compiler sagt mir chain-err-test.go:24: multiple-value c.funA() in single-value context
und nicht kompiliert wird. Ist es ein guter Weg, so funcA, funcB und funcC kann einen Fehler melden und zu stoppen, die Kette?
- Sie können Panik, aber natürlich bedeutet dies, müssen Sie zum wiederherstellen auf jede Methode oder an der Wurzel. Sie können auch die
Chain
Objekt stateful mit einem Fehler, und überprüfen Sie es für jede Methode. - stimmt, aber ich Frage mich, ob es eine gute idiomatische Weise, dies zu tun. In meiner Welt Fehlerbedingungen sind überall, und an einigen Orten (z.B. Operatoren wie golangpatterns.info/object-oriented/operators ) eine solche Verkettung sollte eine gute API. (das erste Beispiel auf dieser Seite also ist das nicht eine gute API - entweder Sie haben Tonnen von Funktionen für alle Typen oder einen Schalter, wo falsche Typen sind nicht vom compiler erkannt)
- Ich erinnere mich an eine schönere API mit Funktionen zurückgeben Funktionen, wie in dave.cheney.net/2014/10/17/functional-options-for-friendly-apis (nach commandcenter.blogspot.com.au/2014/01/...). Ist es nicht genau das "chaining", obwohl.
- Ich Tat etwas ähnlich, aber verwendet Kanälen-chain-output-streams und eine Fehlermeldung schließt sich einfach der Kanal, Abwicklung des gesamten Kette. Es ist wahrscheinlich nicht das, was Sie brauchen obwohl.
- Ich weiß, das ist nicht die Antwort, die du suchst, aber die idiomatische Sache ist zu vermeiden Verkettung. Es ist nichts falsch mit Verkettung, aber es ist eine Konsequenz aus dem Vokabular der Verwendung einer error-Werte anstelle von exceptions.
- auch wenn es keinen guten Weg, dann ist Ihre Antwort unten könnte gut sein, meine Hoffnung war, dass habe ich übersehen, eine Sache noch Recht unerfahren in Gehen.
- Ich denke, das ist, was Sie finden. Gehen an Orte, Sprache Einfachheit sehr hoch, und "klug" workarounds zu verhängen, um andere Idiome sind oft schwierig, auch wenn das Ergebnis weniger boilerplate (und das ist auch richtig so; idiomatische boilerplate ist noch viel mehr lesbar als "clever", nicht-idiomatische Lösung). Wieder, dies bedeutet nicht, dass die Verkettung von Methoden ist eine schlechte Praxis--es ist einfach nicht gut Gehen.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Leider Nein, es gibt keine gute Lösung für Ihr problem. Problemumgehungen sind ausreichend Komplex (hinzufügen von Fehler-Kanäle, etc), die die Kosten übersteigen den Gewinn.
Method chaining ist nicht ein idiom Gehen (zumindest nicht für die Methoden, die möglicherweise Fehler). Dies ist nicht, weil es gibt nichts besonders falsch mit Ketten-Methode, sondern eine Folge von dem idiom der Fehler zurückgeben, anstatt in Panik zu geraten. Die anderen Antworten sind workarounds, aber keine sind idiomatisch.
Gute Frage, aber es ist nicht, weil Go unterstützt mehrere gibt. Python unterstützt mehrere gibt, und Java kann auch über eine
Tuple<T1, T2>
Klasse; Methode-Ketten sind Häufig in beiden Sprachen. Der Grund, dass diese Sprachen können Weg mit es, weil Sie idiomatically kommunizieren Fehler über exceptions. Ausnahmen stoppen Sie die Methode, die Kette sofort und springen Sie zu der entsprechenden exception-handler. Dies ist das Verhalten, das die Go-Entwickler wurden speziell versuchen zu vermeiden, indem Sie den Fehler zurück, statt.(foo, nil).Bar()
nur um die Verkettung von Methoden. Die wirkliche Lösung für dieses problem (sofern es ein problem ist) ist Monaden. Definieren Sie einen Kurzschluss-ein-Fehler-Monade und die Kette so:foo >>= bar >>= baz
(wo die bar nimmt einen FooResult, der baz und nimmt eine BarResult), aber dies erfordert eine komplexere Typ-system für die vor-und Nachteile (insbesondere eine steilere Lernkurve und weniger Konsistenz der Programme, nicht zu vergessen einen besser optimierenden compiler zur Aufrechterhaltung der Leistungsfähigkeit).Können Sie versuchen, wie, dass:
https://play.golang.org/p/dVn_DGWt1p_H
Wenn man die Kontrolle über den code und die Funktion, die Signatur ist identisch schreiben Sie etwas wie:
Spielplatz
*Chain
Objekt? Sie sind nicht etwas zu tun mit es. Sogar noch, ist dies eine clevere Lösung, aber es ist die clevere Art, das ist schlechter lesbar als die Schriftif err := funX(); err != nil { /* do something */ }
für X={A, B, C} beziehungsweise.Können Sie machen Sie Ihre Kette faul durch das sammeln ein Stück funtions
Wie wäre dieser Ansatz: Erstellen Sie ein struct, dass die Delegierten
Chain
underror
, und senden Sie es anstelle von zwei Werten. z.B.:funC()
; der zurückgegebene Fehler durchfunA()
undfunB()
werden ignoriert.