Menu
Coddy logo textTech

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.

challenge icon

Desafío

Fácil

Vamos 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:

    • ErrEmptyContent con el mensaje "file content is empty"
    • ErrInvalidFormat con el mensaje "invalid configuration format"

    Crea un tipo de error personalizado ParseError con los campos Line (int) y Message (string). Su método Error() 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 ConfigParser con un campo booleano parsed para rastrear si el análisis se completó con éxito.

    Implementa estos métodos:

    • NewConfigParser() *ConfigParser - crea un nuevo analizador con parsed establecido en false
    • ParseLine(lineNum int, line string) error - valida una sola línea. Si la línea no contiene un carácter =, devuelve un *ParseError con el número de línea y el mensaje "missing key-value separator". De lo contrario, devuelve nil.
    • Parse(content string) error - el método de análisis principal que:
      • Devuelve ErrEmptyContent si el contenido está vacío
      • Devuelve ErrInvalidFormat si el contenido no contiene al menos un carácter de nueva línea
      • Divide el contenido por nuevas líneas y llama a ParseLine para cada línea (los números de línea comienzan en 1)
      • Si ParseLine devuelve un error, envuélvelo con "parsing configuration: %w" y devuélvelo
      • Establece parsed a true en caso de éxito y devuelve nil
    • Status() string - devuelve "ready" si parsed es 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 defer para 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() como errors.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() encuentra ErrEmptyContent: imprime Error: No configuration provided
  • Si errors.Is() encuentra ErrInvalidFormat: imprime Error: Configuration must have multiple lines
  • Si errors.As() encuentra un *ParseError: imprime el error envuelto completo, luego en una nueva línea imprime Fix 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: ready

Y 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 parsed

Prué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