Interfacce Stringer ed Error
Fa parte della sezione Programmazione orientata agli oggetti del percorso GO di Coddy. Lezione 32 di 107.
La libreria standard di Go definisce due interfacce che userai continuamente: fmt.Stringer e error. Entrambe sono semplici interfacce con un singolo metodo, che permettono ai tuoi tipi di integrarsi efficacemente con le funzionalità integrate di Go.
L’interfaccia Stringer si trova nel pacchetto fmt e richiede un solo metodo:
type Stringer interface {
String() string
}Quando implementi String() sul tuo tipo, funzioni come fmt.Println la usano automaticamente per visualizzare il tuo valore:
type Person struct {
Name string
Age int
}
func (p Person) String() string {
return fmt.Sprintf("%s (%d years old)", p.Name, p.Age)
}
func main() {
p := Person{Name: "Alice", Age: 30}
fmt.Println(p) // Alice (30 anni)
}L’interfaccia error è altrettanto semplice e richiede un metodo Error() che restituisca una stringa:
type error interface {
Error() string
}Qualsiasi tipo con un metodo Error() può essere usato come valore di errore in Go. Questo ti permette di creare tipi di errore personalizzati con un contesto aggiuntivo:
type ValidationError struct {
Field string
Message string
}
func (e ValidationError) Error() string {
return fmt.Sprintf("%s: %s", e.Field, e.Message)
}
func main() {
err := ValidationError{Field: "email", Message: "invalid format"}
fmt.Println(err) // email: invalid format
}Queste due interfacce dimostrano la filosofia di Go: interfacce piccole e mirate che sbloccano comportamenti potenti tramite l’implementazione implicita.
Sfida
FacileCostruiamo un sistema di monitoraggio della temperatura che utilizza sia le interfacce Stringer sia error per fornire un output leggibile e una gestione degli errori significativa.
Organizzerai il codice in due file:
temperature.go: crea una structTemperaturecon i campiValue(float64) eUnit(string). Implementa il metodoString()in modo che, quando viene stampata, la temperatura sia visualizzata in un formato leggibile. Crea anche una structTemperatureErrorcon i campiTemp(float64) eReason(string) e implementa il metodoError()per fornire messaggi di errore descrittivi.main.go: crea una funzione chiamataValidateTemperatureche accetta unaTemperaturee restituisce un errore se la temperatura non è valida. Una temperatura non è valida se è inferiore allo zero assoluto (-273.15 per Celsius, -459.67 per Fahrenheit). Se è valida, la funzione restituiscenil. Leggi i dati della temperatura dall'input, crea una Temperature, convalidala e stampa l'output appropriato.
Verranno forniti i seguenti input:
- Riga 1: valore della temperatura (float)
- Riga 2: unità (
Cper Celsius oFper Fahrenheit)
Il tuo metodo String() dovrebbe restituire il formato:
[Value] degrees [Unit]Dove Unit è la parola completa "Celsius" o "Fahrenheit", in base all'input.
Il tuo metodo Error() dovrebbe restituire il formato:
invalid temperature [Temp]: [Reason]Se la temperatura è valida, stampa la Temperature usando fmt.Println (che utilizzerà il tuo metodo String()). Se non è valida, stampa l'errore (che utilizzerà il tuo metodo Error()).
Ad esempio, dati 25.5 e C, l'output dovrebbe essere:
25.5 degrees CelsiusDati -500 e F, l'output dovrebbe essere:
invalid temperature -500: below absolute zeroUsa "below absolute zero" come motivo quando la temperatura è troppo bassa.
Provalo tu
package main
import (
"fmt"
)
// ValidateTemperature verifica se una temperatura è valida
// Restituisce un errore se la temperatura è inferiore allo zero assoluto
// Zero assoluto: -273.15 per Celsius, -459.67 per Fahrenheit
func ValidateTemperature(t Temperature) error {
// TODO: Implementare la logica di validazione
// Verificare se la temperatura è inferiore allo zero assoluto in base all'unità
// Restituire un TemperatureError se non è valida, nil se è valida
return nil
}
func main() {
var value float64
var unit string
fmt.Scanln(&value)
fmt.Scanln(&unit)
// TODO: Creare una struct Temperature con i valori di input
// TODO: Validare la temperatura usando ValidateTemperature
// TODO: Se si verifica un errore, stamparlo
// Altrimenti, stampare la temperatura (usando il metodo String())
}
Questa lezione include un breve quiz. Inizia la lezione per rispondere e tenere traccia dei tuoi progressi.
Tutte le lezioni di Programmazione orientata agli oggetti
1Fondamenti di OOP in Go
File esterniWorkspace e moduli GoPacchetti e importazioniNomi esportati e non esportatiIntroduzione all’OOP in GoGli struct come classiDefinire metodi sugli structReceiver con puntatore vs receiver con valoreInizializzazione degli structFunzioni costruttriciRiepilogo - Calcolatrice semplice4Interfacce
Introduzione alle interfacceImplementazione implicitaL’interfaccia come contrattoInterfaccia vuota (any)Asserzione di tipoSwitch sul tipoComposizione di interfacceInterfacce Stringer ed ErrorRipasso - Calcolatore di forme7Incapsulamento
Campi esportati e non esportatiIncapsulamento a livello di packageMetodi Getter e SetterNascondimento delle informazioni in GoRiepilogo - Registri degli studenti10Tipi generici (Go 1.18+)
Introduzione ai tipi genericiParametri di tipoVincoli di tipoStruct genericheSoluzione alternativa per i metodi genericiRiepilogo - Collezione generica13Modelli di progettazione Parte 1
Introduzione ai modelli di progettazioneModello SingletonModello FactoryModello Abstract FactoryModello ObserverModello Strategy2Approfondimento su tipi e struct
Tipi di base e compostiDefinizioni di tipi personalizzatiTag delle structStruct anonimeStruct annidateValori zero e predefinitiRipasso - Rubrica5Composizione invece dell'ereditarietà
Perché Go non ha l'ereditarietàFondamenti dell'embedding delle structPromozione dei metodiEmbedding di più structEmbedding e aggregazione a confrontoMascheramento dei metodi embeddedRiepilogo: gerarchia dei dipendenti8Gestione degli errori e OOP
L'interfaccia errorTipi di errore personalizzatiWrapping degli errori (fmt.Errorf)Errori sentinellaerrors.Is() ed errors.As()Panic, Defer e RecoverRiepilogo - Parser di file11Libreria standard e OOP
io.Reader e io.Writersort.InterfaceInterfaccia fmt.Stringerencoding/json con le structInterfaccia http.HandlerRipasso - modelli REST API14Modelli di progettazione – Parte 2
Pattern CommandPattern AdapterPattern DecoratorPattern Template MethodPattern StatePattern CompositeMiddleware come Decorator3Puntatori e memoria
Concetti base dei puntatori in GoPuntatori a structPassaggio per valore vs per riferimentoLa funzione new()Garbage collection in GoRiepilogo - Costruttore di liste concatenate6Polimorfismo in Go
Polimorfismo tramite interfacceDuck typing in GoRegole di soddisfacimento delle interfacceCollezioni polimorficheIniezione delle dipendenzeRiepilogo - Elaboratore di pagamenti9Concorrenza e OOP
Basi delle goroutineCanali e comunicazioneCanali bufferizzati vs non bufferizzatiIstruzione selectsync.Mutex e sync.RWMutexsync.WaitGroupProgettazione di struct thread-safeRiepilogo: worker poolEsercitati da solo: Compilatore Go online