Nessun risultato. Prova con un altro termine.
Guide
Notizie
Software
Tutorial

Gestione degli errori

Scopriamo la sintassi del linguaggio di programmazione Go che ci permette di intercettare e gestire opportunamente gli errori.
Scopriamo la sintassi del linguaggio di programmazione Go che ci permette di intercettare e gestire opportunamente gli errori.
Link copiato negli appunti

Quando si programma è fondamentale valutare come funziona il nostro codice ma soprattutto capire se e perchè non funziona correttamente. Gli errori
stessi possono essere di vario genere e soprattutto quando sono annidati nella logica può diventare davvero difficile stanarli. Gli errori però, spesso, possono essere nostri
amici in quanto permettono di segnalare rapidamente situazioni anomale e attivare le opportune procedure di recupero: tutto sta nella modalità di segnalazione che scegliamo.
Anche in Go quindi, come in ogni altro linguaggio, è fondamentale saperli evitare ma soprattutto saperli gestire.

L'approccio Go

La gestione degli errori ha subito una certa evoluzione nella storia della programmazione e soprattutto si è adattata ai vari paradigmi adottati. Nei linguaggi
procedurali si tendeva tipicamente a restituire un valore specifico per segnalare un errore. Ad esempio, una funzione che restituiva un risultato numerico poteva
fornire valori come -1 o zero in caso di errore. Ma qualora valori negativi o zero fossero stati possibili risultati validi come si sarebbe potuto distinguere i casi di errore da un risultato corretto?
Perciò molto spesso si finiva nel tentare di prevenire l'errore facendo controlli a priori che comportavano comunque all'introduzione di ulteriore logica - spesso invasiva -
che non garantiva nemmeno protezione nel cento per cento dei casi.

Con l'avvento della programmazione a oggetti, si sono fatte largo le eccezioni, strutture sintattiche esterne, poco invasive, in grado di intercettare l'errore
una volta scattato senza alcuna intenzione di evitarlo. In Go, si è scelto un approccio intermedio sfruttando soprattutto la capacità delle funzioni
di restituire più risultati e alcuni elementi introdotti in uno specifico package denominato errors. Vediamolo al lavoro.

Gestire errori

La regola è: se una funzione restituisce più risultati l'ultimo di questi indica se si è verificato un errore o meno. Ad esempio, supponiamo di avere
una funzione denominata verifica_maggiorenne che determina se un'età immessa come argomento indica una persona maggiorenne o meno (i 18 anni segneranno l'inizio
della maggiore età):

func verifica_maggiorenne(eta int) bool {
	return eta >= 18
}

Invocando verifica_maggiorenne(23) otterremo true (persona maggiorenne), invocando verifica_maggiorenne(12) otterremo false (persona minorenne). Perfetto!
Ma qualora passassimo verifica_maggiorenne(-100) otterremmo false in quanto il numero -100 è effettivamente minore di 18. Eppure un risultato
formalmente corretto si è basato su un errore in quanto -100 non può essere un età in quanto numero negativo. Come poter quindi riconoscere un risultato
apparentemente corretto ma che sotto sotto cela un'anomalia? Useremo l'approccio Go, forniremo un secondo valore di risposta che rappresenterà se il risultato è corretto o meno.

Ecco una possibile implementazione:

func verifica_maggiorenne(eta int) (bool, error) {
	if eta >= 0 {
		return eta >= 18, nil
	}
	return false, errors.New("l'argomento eta non può essere inferiore a zero!")
}

Notiamo per prima cosa che la funzione ha un doppio tipo di ritorno: (bool, error) il primo per indicare se l'età rappresenta una persona
maggiorenne, il secondo per definire l'errore. Tra i package che useremo dovremo importare anche errors che ci offrirà tutti i tipi di dato per
la gestione degli errori.

Se l'età è almeno zero l'errore restituito sarà nil ovvero niente pertanto la funzione avrà potuto lavorare normalmente.
Altrimenti, il secondo risultato sarà un oggetto di errore con tanto di messaggio.

Per provare il tutto potremo usare il seguente codice:

eta := 10
if risultato, errore := verifica_maggiorenne(eta); errore != nil {
   fmt.Println("ERRORE: ", errore)
} else {
   fmt.Println("Risultato: ", risultato)
}

Notiamo come nell'if vengano raccolti entrambi i risultati con risultato, errore := verifica_maggiorenne(eta) in modo da poter subito verificare
se errore è nil. In virtù di quest'ultimo confronto capiremo se il primo risultato potrà essere usato o meno. Si potrà
ripetere la prova più volte variando il valore di eta: in questo caso, impostato a 10, avrà restituito false con assenza di errore.

Per una prova agevole e riepilogativa potremo includere il tutto in una funzione come nel seguente programma:

package main
import (
	"errors"
	"fmt"
)
func verifica_maggiorenne(eta int) (bool, error) {
	if eta >= 0 {
		return eta >= 18, nil
	}
	return false, errors.New("l'argomento eta non può essere inferiore a zero!")
}
func verifica_eta(eta int) {
	if risultato, errore := verifica_maggiorenne(eta); errore != nil {
		fmt.Println("ERRORE per", eta, ": ", errore)
	} else {
		fmt.Println("Risultato per ", eta, ": ", risultato)
	}
}
func main() {
	verifica_eta(10)
	verifica_eta(24)
	verifica_eta(-100)
}

ottenendo in output questo:

Risultato per  10 :  false
Risultato per  24 :  true
ERRORE per -100 :  l'argomento eta non può essere inferiore a zero!

Ti consigliamo anche