Recapitulação - File Parser
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 ExternosGo Workspace e MódulosPacotes e ImportaçõesNomes Exportados vs Não ExportadosIntrodução a OOP em GoStructs como ClassesDefinindo Métodos em StructsRecebedores de Ponteiro vs ValorInicialização de StructsFunções ConstrutorasRecapitulação - Calculadora Simples4Interfaces
Introdução a InterfacesImplementação ImplícitaInterface como ContratoInterface Vazia (any)Type AssertionType SwitchComposição de InterfacesInterfaces Stringer & ErrorRecapitulação - Calculadora de Formas7Encapsulamento
Campos Exportados vs Não ExportadosEncapsulamento em Nível de PacoteMétodos Getter e SetterOcultação de Informação em GoRecapitulação - Registros de Estudantes10Generics (Go 1.18+)
Introdução a GenericsParâmetros de TipoRestrições de TipoStructs GenéricasSolução Alternativa para Métodos GenéricosRecapitulação - Coleção Genérica2Mergulho Profundo em Tipos e Structs
Tipos Básicos e CompostosDefinições de Tipos PersonalizadosStruct TagsStructs AnônimasStructs AninhadasZero Values e PadrõesRecapitulação - Agenda de Contatos5Composição em vez de Herança
Por que Go não possui HerançaFundamentos de Incorporação de StructsPromoção de MétodosIncorporando Múltiplas StructsIncorporação vs AgregaçãoShadowing de Métodos IncorporadosRecapitulação - Hierarquia de Funcionários8Tratamento de Erros e OOP
A Interface errorTipos de Erro PersonalizadosError Wrapping (fmt.Errorf)Erros Sentinelaerrors.Is() e errors.As()Panic, Defer e RecoverRecapitulação - File Parser3Ponteiros e Memória
Fundamentos de Ponteiros em GoPonteiros para StructsPassagem por Valor vs ReferênciaA Função new()Garbage Collection em GoRecapitulação - Construtor de Lista Encadeada6Polimorfismo em Go
Polimorfismo via InterfacesDuck Typing em GoRegras de Satisfação de InterfaceColeções PolimórficasInjeção de DependênciaRecapitulação - Processador de Pagamentos9Concorrência e OOP
Fundamentos de GoroutinesCanais e ComunicaçãoCanais com Buffer vs. Sem BufferInstrução Selectsync.Mutex e sync.RWMutexsync.WaitGroupDesign de Structs Thread-SafeRecapitulação - Worker Pool