Mehr als einen Wert zurückgeben
Schreib die Ergebnistypen in Klammern. Gib die Werte durch Kommas getrennt zurück und empfange sie auf dieselbe Weise.
Die eingebauten Funktionen min und max gibt es seit Go 1.21. Der Aufrufer muss jedes Ergebnis empfangen: x := minMax(nums) kompiliert nicht und meldet assignment mismatch: 1 variable but minMax returns 2 values.
Die Konvention (value, error)
Der häufigste Grund, zwei Werte zurückzugeben, ist das Melden eines Fehlschlags. Per Konvention kommt der Fehler zuletzt, und wenn er nicht nil ist, gelten die anderen Ergebnisse als bedeutungslos.
Ausgabe:
port: 8080
error: port "http": strconv.Atoi: parsing "http": invalid syntax
error: port out of range
Bei einem Fehler gibst du für jedes andere Ergebnis den Nullwert zurück (0, "", nil). Das vollständige Muster mit Wrapping und Prüfung steht auf der Seite zur Fehlerbehandlung.
Das Comma-ok-Idiom
Mehrere eingebaute Operationen geben optional ein zweites bool zurück, das sagt, ob der erste Wert echt ist. Die Variable heißt per Konvention ok.
Diese drei Formen (Map-Lookup, Type Assertion, Empfang aus einem Channel) sind besonders: Sie liefern einen oder zwei Werte, je nachdem, wie vielen Variablen du zuweist. Deine eigenen Funktionen können das nicht. Eine Funktion, die mit zwei Ergebnissen deklariert ist, gibt immer zwei zurück.
Der Blank Identifier
_ nimmt einen Wert entgegen und wirft ihn weg. Nutz ihn für Ergebnisse, die du nicht brauchst:
_, err := fmt.Sscan(input, &n)
key, _ := parseLine(line)
Einen Fehler mit _ zu ignorieren kompiliert, also tu es nur, wenn du weißt, dass der Aufruf nicht fehlschlagen kann oder ein Fehlschlag egal ist. strings.Builder.WriteString zum Beispiel gibt immer einen nil-Fehler zurück; beim Schließen einer Datei nach dem Schreiben ist das nicht so.
Benannte Ergebnisse
Ergebnisparameter können Namen haben. Sie werden am Anfang der Funktion deklariert, mit ihren Nullwerten initialisiert, und ein return ohne Werte gibt zurück, was sie gerade enthalten.
Die Namen erscheinen in der Ausgabe von go doc. Das hilft, wenn zwei Ergebnisse denselben Typ haben: (quotient, remainder int) sagt mehr als (int, int).
Ein nacktes return in einer langen Funktion ist schwer zu lesen, weil der Leser zurückscrollen muss, um zu sehen, was die Ergebnisse enthalten. Der übliche Rat: Benenne Ergebnisse, wenn die Namen etwas dokumentieren, und schreib trotzdem explizit return quotient, remainder, außer die Funktion ist nur ein paar Zeilen lang.
Benannte Ergebnisse und defer
Eine per defer aufgerufene Funktion läuft, nachdem die return-Anweisung die Ergebnisse gesetzt hat, und bevor der Aufrufer sie erhält. Mit benannten Ergebnissen kann sie diese lesen und ändern. So ergänzt du jeden Fehler, den eine Funktion zurückgibt, um Kontext, oder machst aus einer Panic einen Fehler.
Das gibt load : empty name und dann <nil> aus. return errors.New(...) weist zuerst err zu, dann wrappt die defer-Funktion den Fehler. Mehr dazu unter defer.
Ein benanntes Ergebnis verschatten
Benannte Ergebnisse leben im äußersten Scope der Funktion. Ein := in einem verschachtelten Block erzeugt eine neue Variable mit demselben Namen, und ein nacktes return gibt dann die äußere zurück.
func find() (n int, err error) {
if true {
n, err := compute() // new n and err, shadowing the results
_ = n
_ = err
}
return // returns 0, nil
}
Den schlimmsten Fall fängt der Compiler ab: Ein nacktes return innerhalb des Blocks, in dem ein Ergebnis verschattet ist, scheitert mit result parameter err not in scope at return. Die Version oben, bei der das Return außerhalb des Blocks steht, fängt er nicht ab. Nimm = statt :=, wenn du die Ergebnisvariablen meinst.
Häufige Fehler
- Den Wert benutzen, obwohl err nicht nil ist. Prüf zuerst
err. Eine Funktion darf neben einem Fehler beliebigen Müll zurückgeben. - Einen typisierten nil-Pointer als Fehler zurückgeben.
var e *MyErr; return egibt einenerrorzurück, der nicht nil ist. Gib bei Erfolg ein wörtlichesnilzurück. - Zu viele Ergebnisse. Drei oder mehr Ergebnisse mit gemischter Bedeutung sind unhandlich. Gib stattdessen ein Struct zurück.
Häufig gestellte Fragen
Wie gibt man in Go mehrere Werte aus einer Funktion zurück?
Schreib die Ergebnistypen in Klammern und gib die Werte durch Kommas getrennt zurück: func minMax(xs []int) (int, int) { ...; return lo, hi }. Der Aufrufer weist sie alle auf einmal zu: lo, hi := minMax(nums).
Wie ignoriere ich in Go einen der Rückgabewerte?
Weise ihn dem Blank Identifier _ zu: _, err := strconv.Atoi(s) oder n, _ := strconv.Atoi(s). Ganz weglassen kannst du einen Wert nicht: Die Anzahl der Variablen links muss der Anzahl der Ergebnisse entsprechen.
Was sind benannte Rückgabewerte in Go?
Ergebnisparameter mit Namen, etwa func split(n int) (half, rest int). Sie starten mit ihren Nullwerten, können im Rumpf zugewiesen werden, und ein nacktes return gibt ihre aktuellen Werte zurück. Außerdem kann eine per defer aufgerufene Funktion damit ändern, was der Aufrufer bekommt.
Sollte ich in Go Naked Returns verwenden?
Nur in kurzen Funktionen. Ein nacktes return in einer langen Funktion verbirgt, was zurückgegeben wird, und macht Shadowing-Bugs leicht. Die Go-Styleguides empfehlen, Ergebnisse zur Dokumentation zu benennen und in allem, was länger als ein paar Zeilen ist, explizite Werte zurückzugeben.