Recapitulação - Analisador de Arquivos
Parte da seção Programação Orientada a Objetos do Journey de GO da Coddy. Lição 58 de 107.
Desafio
FácilVamos construir um analisador de arquivos de configuração que reúna todas as técnicas de tratamento de erros deste capítulo. Seu analisador lidará com múltiplos cenários de falha com tipos de erro personalizados, erros sentinela, encapsulamento de erros (error wrapping) e limpeza adequada usando defer.
Você organizará seu código em três arquivos:
errors.go: Defina sua infraestrutura de erro para o analisador.Crie dois erros sentinela:
ErrEmptyContentcom a mensagem"file content is empty"ErrInvalidFormatcom a mensagem"invalid configuration format"
Crie um tipo de erro personalizado
ParseErrorcom os camposLine(int) eMessage(string). Seu métodoError()deve retornar:parse error at line [Line]: [Message]parser.go: Construa o analisador de configuração com tratamento de erros em camadas.Crie uma struct
ConfigParsercom um campo booleanoparsedpara rastrear se a análise foi concluída com sucesso.Implemente estes métodos:
NewConfigParser() *ConfigParser- cria um novo analisador comparseddefinido comofalseParseLine(lineNum int, line string) error- valida uma única linha. Se a linha não contiver um caractere=, retorne um*ParseErrorcom o número da linha e a mensagem"missing key-value separator". Caso contrário, retornenil.Parse(content string) error- o método principal de análise que:- Retorna
ErrEmptyContentse o conteúdo estiver vazio - Retorna
ErrInvalidFormatse o conteúdo não contiver pelo menos um caractere de nova linha - Divide o conteúdo por novas linhas e chama
ParseLinepara cada linha (os números das linhas começam em 1) - Se
ParseLineretornar um erro, envolva-o com"parsing configuration: %w"e retorne - Define
parsedcomotrueem caso de sucesso e retornanil
- Retorna
Status() string- retorna"ready"separsedfor true, caso contrário, retorna"not parsed"
main.go: Leia o conteúdo da configuração e demonstre uma inspeção de erros abrangente.Leia duas linhas de entrada que juntas formam o conteúdo da configuração (junte-as com uma nova linha). Use
deferpara sempre imprimir o status do analisador ao final, independentemente do sucesso ou falha.Após tentar analisar, inspecione qualquer erro usando tanto
errors.Is()quantoerrors.As()para fornecer um feedback específico baseado no que deu errado.
As seguintes entradas serão fornecidas:
- Linha 1: Primeira linha do conteúdo da configuração
- Linha 2: Segunda linha do conteúdo da configuração
Trate os erros com mensagens específicas:
- Se
errors.Is()encontrarErrEmptyContent: imprimaError: No configuration provided - Se
errors.Is()encontrarErrInvalidFormat: imprimaError: Configuration must have multiple lines - Se
errors.As()encontrar um*ParseError: imprima o erro completo encapsulado e, em uma nova linha, imprimaFix line [Line]: [Message] - Se a análise for bem-sucedida: imprima
Configuration parsed successfully
Após tratar o resultado (sucesso ou erro), o status adiado (deferred) deve ser impresso em uma nova linha: Parser status: [status]
Por exemplo, dados host=localhost e port=8080, sua saída deve ser:
Configuration parsed successfully
Parser status: readyE dados host=localhost e invalid line, sua saída deve ser:
parsing configuration: parse error at line 2: missing key-value separator
Fix line 2: missing key-value separator
Parser status: not parsedExperimente você mesmo
package main
import (
"bufio"
"errors"
"fmt"
"os"
)
func main() {
reader := bufio.NewReader(os.Stdin)
// Ler a primeira linha da configuração
line1, _ := reader.ReadString('\n')
line1 = line1[:len(line1)-1] // Remover a quebra de linha final
// Ler a segunda linha da configuração
line2, _ := reader.ReadString('\n')
if len(line2) > 0 && line2[len(line2)-1] == '\n' {
line2 = line2[:len(line2)-1]
}
// Juntar as duas linhas com uma quebra de linha para formar o conteúdo da configuração
content := line1 + "\n" + line2
// Criar um novo parser
parser := NewConfigParser()
// TODO: Usar defer para sempre imprimir o status do parser ao final
// Formato: "Parser status: [status]"
// TODO: Tentar analisar o conteúdo
// TODO: Tratar erros usando errors.Is() e errors.As()
// - Se errors.Is() encontrar ErrEmptyContent: imprimir "Error: No configuration provided"
// - Se errors.Is() encontrar ErrInvalidFormat: imprimir "Error: Configuration must have multiple lines"
// - Se errors.As() encontrar um *ParseError: imprimir o erro completo envolvido,
// então em uma nova linha imprimir "Fix line [Line]: [Message]"
// - Se a análise for bem-sucedida: imprimir "Configuration parsed successfully"
_ = errors.Is // dica: use errors.Is para erros sentinela
_ = errors.As // dica: use errors.As para tipos de erro personalizados
_ = fmt.Println
}
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