Menu

If else in Golang: sintassi, istruzioni di inizializzazione e if err != nil

Come funzionano if, else if ed else in Go: niente parentesi, graffe obbligatorie, l'if con una clausola di inizializzazione e il suo scope, l'idioma if err != nil e i return anticipati al posto dell'annidamento profondo.

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

L'if di Go non ha parentesi attorno alla condizione, richiede sempre le graffe e può iniziare con una breve istruzione che dichiara variabili con scope limitato all'if.

Le condizioni vengono controllate dall'alto e viene eseguito il primo ramo vero. else if ed else sono facoltativi.

Regole di sintassi

Tre regole sono diverse da C, Java e JavaScript:

  1. Niente parentesi attorno alla condizione. if (x > 5) compila, ma gofmt toglie le parentesi.
  2. Le graffe sono obbligatorie, anche per una sola istruzione. Non esiste un if x > 5 return senza graffe.
  3. else va sulla stessa riga della graffa di chiusura. Go inserisce un punto e virgola dopo una } a fine riga, quindi questo fallisce:
if x > 5 {
	fmt.Println("big")
}
else {
	fmt.Println("small")
}
syntax error: unexpected keyword else, expected }

Scrivi } else { su una riga sola.

La condizione deve essere un bool. Go non tratta 0, "" o nil come falso, quindi if count {} e if name {} non compilano. Confronta in modo esplicito: if count > 0, if name != "", if user != nil.

Combina le condizioni con && (e), || (o) e ! (non). Sia && sia || sono in cortocircuito, il che rende sicuri i controlli su nil:

if user != nil && user.IsAdmin() {
	// user.IsAdmin() is only called when user is not nil
}

if con istruzione di inizializzazione

Un if può eseguire una breve istruzione prima della condizione, separata da un punto e virgola. Le variabili dichiarate lì sono visibili in ogni ramo di quell'if, e da nessun'altra parte dopo:

Questo schema tiene le variabili di breve durata fuori dallo scope circostante. Compare di continuo con le ricerche nelle map (v, ok := m[k]), le type assertion (s, ok := v.(string)) e gli errori.

Il rovescio della medaglia: se il valore ti serve dopo l'if, dichiaralo prima. Un errore comune è mettere un risultato nell'istruzione di inizializzazione e poi provare a usarlo più sotto.

L'idioma if err != nil

Le funzioni che possono fallire restituiscono un error per ultimo. Controllalo subito, gestiscilo o restituiscilo, e prosegui con il percorso normale senza indentazione:

Nota che non c'è nessun else dopo if err != nil { return ... }. Lo stile Go gestisce l'errore, ritorna e lascia il flusso normale sul margine sinistro. La pagina sulla gestione degli errori tratta il wrapping e il controllo dei tipi di errore.

Return anticipati invece dell'annidamento

I blocchi if annidati in profondità sono difficili da leggere. Inverti le condizioni e ritorna in anticipo; ogni controllo si legge allora come una guardia:

// Nested
func canCheckout(u *User, cart *Cart) bool {
	if u != nil {
		if u.Verified {
			if len(cart.Items) > 0 {
				return true
			}
		}
	}
	return false
}

// Guards
func canCheckout(u *User, cart *Cart) bool {
	if u == nil || !u.Verified {
		return false
	}
	if len(cart.Items) == 0 {
		return false
	}
	return true
}

Chi programma in Go lo chiama tenere il percorso felice allineato a sinistra. I linter come revive segnalano un else dopo un blocco che termina con return, perché quell'else aggiunge indentazione per niente.

if/else o switch

Una lunga catena di else if che confronta un valore con diversi casi si legge meglio come switch. Uno switch senza espressione sostituisce una catena if/else if di condizioni qualsiasi:

switch {
case score >= 90:
	return "A"
case score >= 80:
	return "B"
default:
	return "F"
}

Usa if per uno o due rami, e switch da tre in su.

Niente operatore ternario

Go non ha cond ? a : b. Assegna con un if:

label := "odd"
if n%2 == 0 {
	label = "even"
}

La pagina sull'operatore ternario spiega il perché e mostra le alternative.

Errori comuni

  • Shadowing con :=. if x, err := f(); err == nil { ... } dichiara una nuova x valida solo per l'if. Una x esterna non viene aggiornata.
  • Assegnazione nella condizione. if x = 5 {} è un errore di compilazione (cannot use assignment x = 5 as value), non un bug silenzioso come in C. Usa ==.
  • Confrontare float con ==. if total == 0.3 fallisce con valori calcolati. Confronta con una tolleranza.
  • Controllare l'errore sbagliato. Dopo a, err := f() e b, err := g(), assicurati che ogni if err != nil stia subito dopo la sua chiamata.

Domande frequenti

Come si scrive if else in Go?

Senza parentesi attorno alla condizione, e con le graffe sempre obbligatorie:

if x > 10 {
	fmt.Println("big")
} else if x > 5 {
	fmt.Println("medium")
} else {
	fmt.Println("small")
}

else deve stare sulla stessa riga della graffa di chiusura del blocco precedente.

Cos'è un if con istruzione di inizializzazione in Go?

Una breve istruzione prima della condizione, separata da un punto e virgola: if n, err := strconv.Atoi(s); err != nil { ... }. Le variabili dichiarate lì esistono solo dentro l'if e nei suoi rami else if ed else, così non finiscono nel resto della funzione.

Posso scrivere un if su una sola riga in Go?

Non senza graffe. if ok return e if (ok) x = 1; sono errori di sintassi. La forma più corta è if ok { return }, e gofmt mette il corpo su una riga a parte. Go non ha nemmeno l'operatore ternario, quindi un valore condizionale richiede un if/else o una piccola funzione di supporto.

Perché Go usa if err != nil ovunque?

Go non ha eccezioni. Le funzioni che possono fallire restituiscono un error come ultimo risultato, e chi le chiama lo controlla subito con if err != nil. La ripetizione è il prezzo per avere ogni punto di errore visibile dove succede.

Illustrazione dei linguaggi di programmazione di Coddy

Impara a programmare con Coddy

INIZIA