Zusammenfassung – Datei-Parser
Teil des Abschnitts Objektorientierte Programmierung der GO-Journey von Coddy — Lektion 58 von 107.
Aufgabe
EinfachLassen 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:
ErrEmptyContentmit der Nachricht"file content is empty"ErrInvalidFormatmit der Nachricht"invalid configuration format"
Erstellen Sie einen benutzerdefinierten Fehlertyp
ParseErrormit den FeldernLine(int) undMessage(string). SeineError()-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 Feldparsed, um zu verfolgen, ob das Parsing erfolgreich abgeschlossen wurde.Implementieren Sie diese Methoden:
NewConfigParser() *ConfigParser- erstellt einen neuen Parser, wobeiparsedauffalsegesetzt ist.ParseLine(lineNum int, line string) error- validiert eine einzelne Zeile. Wenn die Zeile kein=-Zeichen enthält, geben Sie einen*ParseErrormit der Zeilennummer und der Nachricht"missing key-value separator"zurück. Andernfalls geben Sienilzurück.Parse(content string) error- die Haupt-Parsing-Methode, die:ErrEmptyContentzurückgibt, wenn der Inhalt leer istErrInvalidFormatzurückgibt, wenn der Inhalt nicht mindestens ein Zeilenumbruchzeichen enthält- Den Inhalt nach Zeilenumbrüchen aufteilt und
ParseLinefür jede Zeile aufruft (Zeilennummern beginnen bei 1) - Wenn
ParseLineeinen Fehler zurückgibt, diesen mit"parsing configuration: %w"wrappt und zurückgibt parsedbei Erfolg auftruesetzt undnilzurückgibt
Status() string- gibt"ready"zurück, wennparsedwahr 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 miterrors.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 FehlerErrEmptyContentfindet: geben SieError: No configuration providedaus - Wenn
errors.Is()den FehlerErrInvalidFormatfindet: geben SieError: Configuration must have multiple linesaus - Wenn
errors.As()einen*ParseErrorfindet: geben Sie den vollständigen gewrappten Fehler aus, und geben Sie dann in einer neuen ZeileFix line [Line]: [Message]aus - Wenn das Parsing erfolgreich ist: geben Sie
Configuration parsed successfullyaus
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: readyUnd 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 parsedProbier 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
1Grundlagen der Go OOP
Externe DateienGo Workspace & ModulePackages & ImportsExportierte vs. nicht-exportierte NamenEinführung in OOP in GoStructs als KlassenMethoden für Structs definierenPointer- vs. Value-ReceiverStruct-InitialisierungKonstruktor-FunktionenZusammenfassung – Einfacher Taschenrechner4Interfaces
Einführung in InterfacesImplizite ImplementierungInterface als VertragLeeres Interface (any)Type AssertionType SwitchInterface-KompositionStringer & Error InterfacesRückblick - Formen-Rechner7Kapselung
Exportierte vs. nicht exportierte FelderKapselung auf Paket-EbeneGetter- & Setter-MethodenInformation Hiding in GoZusammenfassung - Studierendendatensätze10Generics (Go 1.18+)
Einführung in GenericsTypparameterType ConstraintsGenerische StructsWorkaround für generische MethodenZusammenfassung – Generische Collection2Vertiefung: Typen & Structs
Basis- & zusammengesetzte TypenBenutzerdefinierte TypdefinitionenStruct TagsAnonyme StructsVerschachtelte StructsZero Values & StandardwerteZusammenfassung - Kontaktbuch5Komposition statt Vererbung
Warum Go keine Vererbung hatGrundlagen des Struct EmbeddingMethod PromotionEinbetten mehrerer StructsEmbedding vs. AggregationShadowing eingebetteter MethodenZusammenfassung – Mitarbeiter-Hierarchie8Fehlerbehandlung & OOP
Das error-InterfaceEigene FehlertypenError Wrapping (fmt.Errorf)Sentinel-Fehlererrors.Is() und errors.As()Panic, Defer und RecoverZusammenfassung – Datei-Parser3Zeiger & Speicher
Zeiger-Grundlagen in GoZeiger auf StructsWertübergabe vs. ReferenzübergabeDie new() FunktionGarbage Collection in GoWiederholung – Linked List Builder6Polymorphismus in Go
Polymorphismus über InterfacesDuck Typing in GoInterface-ErfüllungsregelnPolymorphe CollectionsDependency InjectionZusammenfassung – Payment Processor9Nebenläufigkeit & OOP
Goroutines GrundlagenChannels & KommunikationGepufferte vs. ungepufferte ChannelsSelect-Anweisungsync.Mutex & sync.RWMutexsync.WaitGroupThread-sicheres Struct-DesignZusammenfassung - Worker Pool