Menu

Valori di ritorno multipli in Golang: (valore, error) e risultati con nome

Le funzioni Go possono restituire più valori. Questa pagina tratta la sintassi, la convenzione (valore, error), l'idioma comma-ok, i risultati con nome, i return nudi e l'identificatore vuoto.

Questa pagina include editor eseguibili: modifica, esegui e vedi subito l'output.

Restituire più di un valore

Elenca i tipi dei risultati tra parentesi. Restituisci i valori separati da virgole, e ricevili allo stesso modo.

Le funzioni predefinite min e max esistono da Go 1.21. Chi chiama deve ricevere ogni risultato: x := minMax(nums) non compila e dà assignment mismatch: 1 variable but minMax returns 2 values.

La convenzione (valore, error)

Il motivo più comune per restituire due valori è segnalare un fallimento. Per convenzione l'errore viene per ultimo, e quando non è nil gli altri risultati vanno considerati privi di significato.

Output:

port: 8080
error: port "http": strconv.Atoi: parsing "http": invalid syntax
error: port out of range

In caso di fallimento restituisci lo zero value per ogni altro risultato (0, "", nil). Lo schema completo, compresi wrapping e controlli, è nella pagina sulla gestione degli errori.

L'idioma comma-ok

Diverse operazioni predefinite restituiscono un secondo valore bool facoltativo che dice se il primo valore è reale. Per convenzione la variabile si chiama ok.

Queste tre forme (ricerca in una map, type assertion, ricezione da un channel) sono speciali: restituiscono uno o due valori a seconda di quante variabili assegni. Le tue funzioni non possono farlo. Una funzione dichiarata con due risultati ne restituisce sempre due.

L'identificatore vuoto

_ riceve un valore e lo butta via. Usalo per i risultati che non ti servono:

_, err := fmt.Sscan(input, &n)
key, _ := parseLine(line)

Ignorare un errore con _ compila, quindi fallo solo quando sai che la chiamata non può fallire o che il fallimento non conta. strings.Builder.WriteString restituisce sempre un errore nil, per esempio; la chiusura di un file dopo averci scritto no.

Risultati con nome

I parametri di risultato possono avere un nome. Vengono dichiarati all'inizio della funzione, inizializzati ai loro zero value, e un return senza valori restituisce quello che contengono.

I nomi compaiono nell'output di go doc, il che aiuta quando due risultati hanno lo stesso tipo: (quotient, remainder int) dice più di (int, int).

Un return nudo in una funzione lunga è difficile da leggere, perché chi legge deve tornare indietro per vedere cosa contengono i risultati. Il consiglio abituale: dai un nome ai risultati quando i nomi documentano qualcosa, e scrivi comunque return quotient, remainder in modo esplicito, a meno che la funzione non sia lunga poche righe.

Risultati con nome e defer

Una funzione in defer viene eseguita dopo che l'istruzione return ha impostato i risultati e prima che chi chiama li riceva. Con i risultati con nome, la funzione in defer può leggerli e cambiarli. È così che aggiungi contesto a qualsiasi errore restituito da una funzione, o trasformi un panic in un errore.

Stampa load : empty name e poi <nil>. return errors.New(...) prima assegna a err, poi la funzione in defer lo avvolge. Approfondisci in defer.

Shadowing di un risultato con nome

I risultati con nome vivono nello scope più esterno della funzione. Un := dentro un blocco annidato crea una nuova variabile con lo stesso nome, e un return nudo restituisce allora quella esterna.

func find() (n int, err error) {
	if true {
		n, err := compute() // new n and err, shadowing the results
		_ = n
		_ = err
	}
	return // returns 0, nil
}

Il compilatore intercetta il caso peggiore: un return nudo dentro il blocco in cui un risultato è oscurato fallisce con result parameter err not in scope at return. Non intercetta la versione qui sopra, dove il return sta fuori dal blocco. Usa = invece di := quando intendi le variabili di risultato.

Errori comuni

  • Usare il valore quando err non è nil. Controlla prima err. Una funzione è libera di restituire valori senza senso insieme a un errore.
  • Restituire un puntatore nil tipizzato come errore. var e *MyErr; return e restituisce un error non nil. In caso di successo restituisci un nil letterale.
  • Troppi risultati. Tre o più risultati con significati diversi sono scomodi da usare. Restituisci invece una struct.

Domande frequenti

Come si restituiscono più valori da una funzione in Go?

Elenca i tipi dei risultati tra parentesi e restituisci i valori separati da virgole: func minMax(xs []int) (int, int) { ...; return lo, hi }. Chi chiama li assegna tutti insieme: lo, hi := minMax(nums).

Come ignoro uno dei valori di ritorno in Go?

Assegnalo all'identificatore vuoto _: _, err := strconv.Atoi(s) oppure n, _ := strconv.Atoi(s). Non puoi tralasciare del tutto un valore: il numero di variabili a sinistra deve corrispondere al numero di risultati.

Cosa sono i valori di ritorno con nome in Go?

Parametri di risultato che hanno un nome, come func split(n int) (half, rest int). Partono dai loro zero value, si possono assegnare nel corpo, e un return senza valori restituisce i loro valori attuali. Permettono anche a una funzione in defer di cambiare ciò che riceve chi chiama.

Dovrei usare i return nudi in Go?

Solo nelle funzioni brevi. Un return senza valori in una funzione lunga nasconde cosa viene restituito e rende facili i bug di shadowing. Le guide di stile di Go consigliano di dare un nome ai risultati per documentarli e di restituire valori espliciti in tutto ciò che supera poche righe.

Illustrazione dei linguaggi di programmazione di Coddy

Impara a programmare con Coddy

INIZIA