Interfaces Stringer e Error
Parte da seção Programação Orientada a Objetos do Journey de GO da Coddy. Lição 32 de 107.
A biblioteca padrão do Go define duas interfaces que você usará constantemente: fmt.Stringer e error. Ambas são interfaces simples de método único que dão aos seus tipos uma integração poderosa com a funcionalidade nativa do Go.
A interface Stringer está no pacote fmt e exige apenas um método:
type Stringer interface {
String() string
}Quando você implementa String() em seu tipo, funções como fmt.Println automaticamente o utilizam para exibir seu valor:
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 anos de idade)
}A interface error é igualmente simples, exigindo um método Error() que retorna uma string:
type error interface {
Error() string
}Qualquer tipo com um método Error() pode ser usado como um valor de erro em Go. Isso permite que você crie tipos de erro personalizados com contexto adicional:
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
}Estas duas interfaces demonstram a filosofia do Go: interfaces pequenas e focadas que desbloqueiam comportamentos poderosos através de implementação implícita.
Desafio
FácilVamos criar um sistema de monitoramento de temperatura que use as interfaces Stringer e error para fornecer uma saída legível e um tratamento de erros significativo.
Você organizará seu código em dois arquivos:
temperature.go: Crie uma structTemperaturecom os camposValue(float64) eUnit(string). Implemente o métodoString()para que, quando impressa, ela exiba a temperatura em um formato legível. Crie também uma structTemperatureErrorcom os camposTemp(float64) eReason(string), e implemente o métodoError()para fornecer mensagens de erro descritivas.main.go: Crie uma função chamadaValidateTemperatureque receba umaTemperaturee retorne um erro se a temperatura for inválida. Uma temperatura é inválida se estiver abaixo do zero absoluto (-273.15 para Celsius, -459.67 para Fahrenheit). Se for válida, a função retornanil. Leia os dados de temperatura da entrada, crie uma Temperature, valide-a e imprima a saída apropriada.
As seguintes entradas serão fornecidas:
- Linha 1: Valor da temperatura (float)
- Linha 2: Unidade (
Cpara Celsius ouFpara Fahrenheit)
Seu método String() deve retornar o formato:
[Value] degrees [Unit]Em que Unit é a palavra completa "Celsius" ou "Fahrenheit", com base na entrada.
Seu método Error() deve retornar o formato:
invalid temperature [Temp]: [Reason]Se a temperatura for válida, imprima a Temperature usando fmt.Println (que usará seu método String()). Se for inválida, imprima o erro (que usará seu método Error()).
Por exemplo, dadas 25.5 e C, sua saída deve ser:
25.5 degrees CelsiusDados -500 e F, sua saída deve ser:
invalid temperature -500: below absolute zeroUse "below absolute zero" como o motivo quando a temperatura estiver muito baixa.
Experimente você mesmo
package main
import (
"fmt"
)
// ValidateTemperature verifica se uma temperatura é válida
// Retorna um erro se a temperatura estiver abaixo do zero absoluto
// Zero absoluto: -273.15 para Celsius, -459.67 para Fahrenheit
func ValidateTemperature(t Temperature) error {
// TODO: Implementar lógica de validação
// Verificar se a temperatura está abaixo do zero absoluto com base na unidade
// Retornar um TemperatureError se for inválida, nil se for válida
return nil
}
func main() {
var value float64
var unit string
fmt.Scanln(&value)
fmt.Scanln(&unit)
// TODO: Criar uma struct Temperature com os valores de entrada
// TODO: Validar a temperatura usando ValidateTemperature
// TODO: Se houver um erro, imprimir o erro
// Caso contrário, imprimir a temperatura (que usará o método String())
}
Esta lição inclui um quiz rápido. Comece a lição para respondê-lo e acompanhar seu progresso.
Todas as lições de Programação Orientada a Objetos
1Fundamentos de OOP em Go
Arquivos ExternosWorkspace e Módulos do GoPacotes e ImportsNomes Exportados vs. Não ExportadosIntrodução à OOP em GoStructs como ClassesDefinindo Métodos em StructsReceptores de Ponteiro vs. de ValorInicialização de StructsFunções ConstrutorasRecapitulação — Calculadora Simples4Interfaces
Introdução às InterfacesImplementação ImplícitaInterface como ContratoInterface Vazia (any)Asserção de TipoSwitch de TipoComposição de InterfacesInterfaces Stringer e ErrorRecapitulação - Calculadora de Formas7Encapsulamento
Campos Exportados vs. Não ExportadosEncapsulamento no Nível de PacoteMétodos Getters e SettersOcultação de Informações em GoRecapitulação - Registros de Alunos10Genéricos (Go 1.18+)
Introdução aos genéricosParâmetros de tipoRestrições de tipoStructs genéricasAlternativa para métodos genéricosRecapitulação - Coleção genérica13Padrões de Projeto — Parte 1
Introdução aos Padrões de ProjetoPadrão SingletonPadrão FactoryPadrão Abstract FactoryPadrão ObserverPadrão Strategy2Tipos e Structs em Profundidade
Tipos Básicos e CompostosDefinições de Tipos PersonalizadosTags de StructStructs AnônimasStructs AninhadasValores Zero e PadrõesRecapitulação - Livro de Contatos5Composição em vez de herança
Por que Go não tem herançaNoções básicas de incorporação de structsPromoção de métodosIncorporação de várias structsIncorporação vs agregaçãoOcultação de métodos incorporadosRecapitulação - Hierarquia de funcionários8Tratamento de Erros e OOP
A interface errorTipos de Erro PersonalizadosEncapsulamento de Erros (fmt.Errorf)Erros Sentinelaerrors.Is() e errors.As()Panic, Defer e RecoverRecapitulação - Analisador de Arquivos3Ponteiros e Memória
Fundamentos de Ponteiros em GoPonteiros para StructsPassagem por Valor vs. ReferênciaA Função new()Coleta de Lixo em GoRecapitulação - Construtor de Lista Ligada6Polimorfismo em Go
Polimorfismo via InterfacesDuck Typing em GoRegras de Satisfação de InterfacesColeções PolimórficasInjeção de DependênciasRecapitulação - Processador de Pagamentos9Concorrência e OOP
Fundamentos de GoroutinesCanais e comunicaçãoCanais com e sem bufferInstrução selectsync.Mutex e sync.RWMutexsync.WaitGroupDesign de structs thread-safeRevisão - Worker PoolPratique por conta própria: Compilador de Go online