Menu
Coddy logo textTech

Zusammenfassung – Datei-Parser

Teil des Abschnitts Objektorientierte Programmierung der GO-Journey von Coddy — Lektion 58 von 107.

challenge icon

Aufgabe

Einfach

Lassen Sie uns einen Konfigurationsdatei-Parser erstellen, der alle Fehlerbehandlungstechniken aus diesem Kapitel zusammenführt. Ihr Parser wird mehrere Fehlerszenarien mit benutzerdefinierten Fehlertypen, Sentinel-Fehlern, Error-Wrapping und ordnungsgemäßer Bereinigung mittels defer behandeln.

Sie werden Ihren Code in drei Dateien organisieren:

  • errors.go: Definieren Sie Ihre Fehler-Infrastruktur für den Parser.

    Erstellen Sie zwei Sentinel-Fehler:

    • ErrEmptyContent mit der Nachricht "file content is empty"
    • ErrInvalidFormat mit der Nachricht "invalid configuration format"

    Erstellen Sie einen benutzerdefinierten Fehlertyp ParseError mit den Feldern Line (int) und Message (string). Seine Error()-Methode sollte Folgendes zurückgeben: parse error at line [Line]: [Message]

  • parser.go: Erstellen Sie den Konfigurations-Parser mit geschichteter Fehlerbehandlung.

    Erstellen Sie ein ConfigParser-Struct mit einem booleschen Feld parsed, um zu verfolgen, ob das Parsing erfolgreich abgeschlossen wurde.

    Implementieren Sie diese Methoden:

    • NewConfigParser() *ConfigParser - erstellt einen neuen Parser, wobei parsed auf false gesetzt ist.
    • ParseLine(lineNum int, line string) error - validiert eine einzelne Zeile. Wenn die Zeile kein =-Zeichen enthält, geben Sie einen *ParseError mit der Zeilennummer und der Nachricht "missing key-value separator" zurück. Andernfalls geben Sie nil zurück.
    • Parse(content string) error - die Haupt-Parsing-Methode, die:
      • ErrEmptyContent zurückgibt, wenn der Inhalt leer ist
      • ErrInvalidFormat zurückgibt, wenn der Inhalt nicht mindestens ein Zeilenumbruchzeichen enthält
      • Den Inhalt nach Zeilenumbrüchen aufteilt und ParseLine für jede Zeile aufruft (Zeilennummern beginnen bei 1)
      • Wenn ParseLine einen Fehler zurückgibt, diesen mit "parsing configuration: %w" wrappt und zurückgibt
      • parsed bei Erfolg auf true setzt und nil zurückgibt
    • Status() string - gibt "ready" zurück, wenn parsed wahr ist, andernfalls "not parsed"
  • main.go: Lesen Sie den Konfigurationsinhalt ein und demonstrieren Sie eine umfassende Fehlerprüfung.

    Lesen Sie zwei Eingabezeilen ein, die zusammen den Konfigurationsinhalt bilden (verbinden Sie diese mit einem Zeilenumbruch). Verwenden Sie defer, um am Ende immer den Status des Parsers auszugeben, unabhängig von Erfolg oder Misserfolg.

    Nach dem Versuch zu parsen, untersuchen Sie jeden Fehler sowohl mit errors.Is() als auch mit errors.As(), um spezifisches Feedback basierend auf der Fehlerursache zu geben.

Die folgenden Eingaben werden bereitgestellt:

  • Zeile 1: Erste Zeile des Konfigurationsinhalts
  • Zeile 2: Zweite Zeile des Konfigurationsinhalts

Behandeln Sie Fehler mit spezifischen Nachrichten:

  • Wenn errors.Is() den Fehler ErrEmptyContent findet: geben Sie Error: No configuration provided aus
  • Wenn errors.Is() den Fehler ErrInvalidFormat findet: geben Sie Error: Configuration must have multiple lines aus
  • Wenn errors.As() einen *ParseError findet: geben Sie den vollständigen gewrappten Fehler aus, und geben Sie dann in einer neuen Zeile Fix line [Line]: [Message] aus
  • Wenn das Parsing erfolgreich ist: geben Sie Configuration parsed successfully aus

Nach der Behandlung des Ergebnisses (Erfolg oder Fehler) sollte der verzögerte Status (deferred status) in einer neuen Zeile ausgegeben werden: Parser status: [status]

Zum Beispiel, gegeben host=localhost und port=8080, sollte Ihre Ausgabe wie folgt aussehen:

Configuration parsed successfully
Parser status: ready

Und gegeben host=localhost und invalid line, sollte Ihre Ausgabe wie folgt aussehen:

parsing configuration: parse error at line 2: missing key-value separator
Fix line 2: missing key-value separator
Parser status: not parsed

Probier es selbst

package main

import (
	"bufio"
	"errors"
	"fmt"
	"os"
)

func main() {
	reader := bufio.NewReader(os.Stdin)
	
	// Erste Zeile der Konfiguration lesen
	line1, _ := reader.ReadString('\n')
	line1 = line1[:len(line1)-1] // Abschließenden Zeilenumbruch entfernen
	
	// Zweite Zeile der Konfiguration lesen
	line2, _ := reader.ReadString('\n')
	if len(line2) > 0 && line2[len(line2)-1] == '\n' {
		line2 = line2[:len(line2)-1]
	}
	
	// Die beiden Zeilen mit einem Zeilenumbruch verbinden, um den Konfigurationsinhalt zu bilden
	content := line1 + "\n" + line2
	
	// Einen neuen Parser erstellen
	parser := NewConfigParser()
	
	// TODO: defer verwenden, um am Ende immer den Status des Parsers auszugeben
	// Format: "Parser status: [status]"
	
	// TODO: Versuchen, den Inhalt zu parsen
	
	// TODO: Fehler mit errors.Is() und errors.As() behandeln
	// - Wenn errors.Is() ErrEmptyContent findet: "Error: No configuration provided" ausgeben
	// - Wenn errors.Is() ErrInvalidFormat findet: "Error: Configuration must have multiple lines" ausgeben
	// - Wenn errors.As() einen *ParseError findet: den vollständigen gewrappten Fehler ausgeben,
	//   dann in einer neuen Zeile "Fix line [Line]: [Message]" ausgeben
	// - Wenn das Parsen erfolgreich ist: "Configuration parsed successfully" ausgeben
	
	_ = errors.Is // Hinweis: errors.Is für Sentinel-Fehler verwenden
	_ = errors.As // Hinweis: errors.As für benutzerdefinierte Fehlertypen verwenden
	_ = fmt.Println
}

Alle Lektionen in Objektorientierte Programmierung