Go introduce l’errore a livello di funzione, ovvero in Go solo una funzione può generare un errore e la sua presenza deve essere dichiarata tramite la parola chiave error
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
package main import ( "errors" "fmt" ) func noerrore(valore string) string { return valore } func possibileerrore(valore string) error { var error error if valore == "prova" { error = errors.New("Valore non ammesso") } return error } func valoreconpossibileerrore(valore string) (string, error) { var error error if valore == "prova" { error = errors.New("Valore non ammesso") } return valore, error } func main() { fmt.Println(noerrore("prova")) fmt.Println(possibileerrore("prova")) fmt.Println(valoreconpossibileerrore("prova")) } |
Nell’esempio ho creato 3 funzioni con 3 comportamenti distinti: la prima non può generare un errore, la seconda può generare un errore, la terza restituisce una stringa e può generare un errore. Per convenzione l’errore è l’ultimo tipo di valore restituito e in assenza di errore esso vale nil. Per generare l’errore ci viene in soccorso il package errors che mette a disposizione la funzione New che genera un errore contenente un testo.
Go ci permette di definire nuovi tipi di errori basati sul comando structs, la cosa fondamentale è che essi implementino l’interafaccia error che presenta il metodo Error da implementare
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
type myError struct { codice int descrizione string } func (e *myError) Error() string { return fmt.Sprintf("%d - %s", e.codice, e.descrizione) } func possibileMyerrore(valore string) error { var error error if valore == "prova" { error = &myError{1, "KO"} } return error } |
In questo caso ho definito un error custom che presenta i campi codice e descrizione. Ho implementato la funzione Error() che sostanzialmente fa il toString dell’errore e implementato un metodo di esempio che lo utilizza
A questo punto il metodo restituisce una interfaccia error e pertanto non sono accessibili i campi della struct definita. Per ovviare a questa limite occorre sfruttare il meccanismo della type assertion che permette di forzare il tipo che si desidera (il meccanismo ricordo il casting di java) e il gioco è fatto.
1 2 3 |
var errore = possibileMyerrore("prova") var er = errore.(*myError) fmt.Println(er.codice) |