Resumen - Analizador de archivos
Parte de la sección Programación Orientada a Objetos del Journey de GO de Coddy — lección 58 de 107.
Desafío
FácilVamos a construir un analizador de archivos de configuración que reúna todas las técnicas de manejo de errores de este capítulo. Tu analizador manejará múltiples escenarios de falla con tipos de error personalizados, errores centinela (sentinel errors), envoltura de errores (error wrapping) y una limpieza adecuada usando defer.
Organizarás tu código en tres archivos:
errors.go: Define tu infraestructura de errores para el analizador.Crea dos errores centinela:
ErrEmptyContentcon el mensaje"file content is empty"ErrInvalidFormatcon el mensaje"invalid configuration format"
Crea un tipo de error personalizado
ParseErrorcon los camposLine(int) yMessage(string). Su métodoError()debe devolver:parse error at line [Line]: [Message]parser.go: Construye el analizador de configuración con manejo de errores por capas.Crea una estructura
ConfigParsercon un campo booleanoparsedpara rastrear si el análisis se completó con éxito.Implementa estos métodos:
NewConfigParser() *ConfigParser- crea un nuevo analizador conparsedestablecido enfalseParseLine(lineNum int, line string) error- valida una sola línea. Si la línea no contiene un carácter=, devuelve un*ParseErrorcon el número de línea y el mensaje"missing key-value separator". De lo contrario, devuelvenil.Parse(content string) error- el método de análisis principal que:- Devuelve
ErrEmptyContentsi el contenido está vacío - Devuelve
ErrInvalidFormatsi el contenido no contiene al menos un carácter de nueva línea - Divide el contenido por nuevas líneas y llama a
ParseLinepara cada línea (los números de línea comienzan en 1) - Si
ParseLinedevuelve un error, envuélvelo con"parsing configuration: %w"y devuélvelo - Establece
parsedatrueen caso de éxito y devuelvenil
- Devuelve
Status() string- devuelve"ready"siparsedes verdadero, de lo contrario"not parsed"
main.go: Lee el contenido de la configuración y demuestra una inspección exhaustiva de errores.Lee dos líneas de entrada que juntas forman el contenido de la configuración (únelas con una nueva línea). Usa
deferpara imprimir siempre el estado del analizador al final, independientemente del éxito o la falla.Después de intentar analizar, inspecciona cualquier error usando tanto
errors.Is()comoerrors.As()para proporcionar comentarios específicos basados en lo que salió mal.
Se proporcionarán las siguientes entradas:
- Línea 1: Primera línea del contenido de configuración
- Línea 2: Segunda línea del contenido de configuración
Maneja los errores con mensajes específicos:
- Si
errors.Is()encuentraErrEmptyContent: imprimeError: No configuration provided - Si
errors.Is()encuentraErrInvalidFormat: imprimeError: Configuration must have multiple lines - Si
errors.As()encuentra un*ParseError: imprime el error envuelto completo, luego en una nueva línea imprimeFix line [Line]: [Message] - Si el análisis tiene éxito: imprime
Configuration parsed successfully
Después de manejar el resultado (éxito o error), el estado diferido debe imprimirse en una nueva línea: Parser status: [status]
Por ejemplo, dados host=localhost y port=8080, tu salida debería ser:
Configuration parsed successfully
Parser status: readyY dados host=localhost y invalid line, tu salida debería ser:
parsing configuration: parse error at line 2: missing key-value separator
Fix line 2: missing key-value separator
Parser status: not parsedPruébalo tú mismo
package main
import (
"bufio"
"errors"
"fmt"
"os"
)
func main() {
reader := bufio.NewReader(os.Stdin)
// Leer la primera línea de configuración
line1, _ := reader.ReadString('\n')
line1 = line1[:len(line1)-1] // Eliminar el salto de línea final
// Leer la segunda línea de configuración
line2, _ := reader.ReadString('\n')
if len(line2) > 0 && line2[len(line2)-1] == '\n' {
line2 = line2[:len(line2)-1]
}
// Unir las dos líneas con un salto de línea para formar el contenido de la configuración
content := line1 + "\n" + line2
// Crear un nuevo analizador (parser)
parser := NewConfigParser()
// TODO: Usar defer para imprimir siempre el estado del analizador al final
// Formato: "Parser status: [status]"
// TODO: Intentar analizar el contenido
// TODO: Manejar errores usando errors.Is() y errors.As()
// - Si errors.Is() encuentra ErrEmptyContent: imprimir "Error: No configuration provided"
// - Si errors.Is() encuentra ErrInvalidFormat: imprimir "Error: Configuration must have multiple lines"
// - Si errors.As() encuentra un *ParseError: imprimir el error envuelto completo,
// luego en una nueva línea imprimir "Fix line [Line]: [Message]"
// - Si el análisis tiene éxito: imprimir "Configuration parsed successfully"
_ = errors.Is // pista: usar errors.Is para errores centinela
_ = errors.As // pista: usar errors.As para tipos de error personalizados
_ = fmt.Println
}
Todas las lecciones de Programación Orientada a Objetos
1Fundamentos de POO en Go
Archivos externosEspacio de trabajo y módulos de GoPaquetes e importacionesNombres exportados vs. no exportadosIntroducción a la POO en GoStructs como clasesDefinición de métodos en structsReceptores de puntero vs. de valorInicialización de structsFunciones constructorasResumen - Calculadora simple4Interfaces
Introducción a las interfacesImplementación implícitaLa interfaz como contratoInterfaz vacía (any)Type AssertionType SwitchComposición de interfacesInterfaces Stringer y ErrorResumen: Calculadora de figuras7Encapsulamiento
Campos exportados vs. no exportadosEncapsulamiento a nivel de paqueteMétodos Getter y SetterOcultamiento de información en GoResumen - Registros de estudiantes10Genéricos (Go 1.18+)
Introducción a los GenéricosParámetros de tipoRestricciones de tipoStructs genéricosSolución alternativa para métodos genéricosResumen - Colección genérica13Patrones de diseño - Parte 1
Introducción a los patrones de diseñoPatrón SingletonPatrón FactoryPatrón Abstract FactoryPatrón ObserverPatrón Strategy2Inmersión profunda en Tipos y Structs
Tipos básicos y compuestosDefiniciones de tipos personalizadosEtiquetas de StructsStructs anónimosStructs anidadosValores cero y por defectoRepaso - Libreta de contactos5Composición sobre herencia
Por qué Go no tiene herenciaConceptos básicos de incrustación de structsPromoción de métodosIncrustación de múltiples structsIncrustación vs AgregaciónShadowing de métodos incrustadosResumen - Jerarquía de empleados8Manejo de Errores y OOP
La interfaz errorTipos de errores personalizadosEnvoltura de errores (fmt.Errorf)Errores centinelaerrors.Is() y errors.As()Panic, Defer y RecoverResumen - Analizador de archivos3Punteros y Memoria
Fundamentos de punteros en GoPunteros a StructsPaso por valor vs referenciaLa función new()Garbage Collection en GoResumen - Constructor de Linked List6Polimorfismo en Go
Polimorfismo mediante interfacesDuck Typing en GoReglas de satisfacción de interfacesColecciones polimórficasInyección de dependenciasResumen - Procesador de pagos9Concurrencia y POO
Fundamentos de GoroutinesChannels y comunicaciónChannels con buffer vs. sin bufferSentencia Selectsync.Mutex y sync.RWMutexsync.WaitGroupDiseño de estructuras Thread-SafeResumen - Worker Pool