Während meiner Arbeit am Aufbau eines Dienstprogramms zur Datentransformation in einem meiner Nebenprojekte musste ich eine JSON-formatierte Datei in das CSV-Format konvertieren. Ich bin auf ein kniffliges Problem gestoßen, dessen Fehlerbehebung fast eine Stunde dauerte, bevor die Grundursache identifiziert werden konnte.
Der Prozess sollte einfach sein und aus drei Hauptschritten bestehen:
func JsonToCSV(data *SrcSheet) { // Create file name in a format like "email_241030172647.csv" (email_yymmddhhmmss.csv) fName := fileName() // Create file f, err := os.Create(fName) if err != nil { log.Println("Unable to create file", err) return } defer f.Close() // Closing to release resources w := csv.NewWriter(f) // Initializing CSV writer // Add header header := []string{"email", "provider", "added_on"} if err = w.Write(header); err != nil { log.Println("Unable to write header", err) return } count := 0 for domain, elm := range data.Email { if err := w.Write(newRecord(domain, elm)); err != nil { log.Println("Unable to add new record", domain, err) return } else { count++ } } log.Println("Number of records written =", count) } func newRecord(email string, e *SrcElements) []string { if e == nil { return nil } DBFormat := "2006-01-02 15:04:05.000" addedOn := time.Now().UTC().Format(DBFormat) r := []string{email, e.Provider, addedOn} return r }
Der Code ist unkompliziert: Erstellen Sie eine neue Datei mit einem bestimmten Namensformat, verschieben Sie deren Schließen, initialisieren Sie den CSV-Writer und beginnen Sie mit dem Schreiben in die Datei. Super einfach, oder?
Schritt 1 und 2 haben gut funktioniert, also habe ich sie weggelassen. Konzentrieren wir uns auf Schritt 3, wo etwas Unerwartetes passierte: Die CSV-Ausgabe enthielt nur 65.032 Datensätze, was bedeutet, dass 310 Datensätze fehlten.
Zur Fehlerbehebung habe ich den Code mit nur 7 JSON-Elementen statt 65.032 ausprobiert. Überraschenderweise wurde überhaupt nichts in die CSV-Datei geschrieben!
Ich habe noch einmal nach einfachen Fehlern gesucht, wie zum Beispiel fehlendem Dateiabschluss, aber alles sah gut aus. Ich habe es dann mit den gesamten 65.032 Elementen erneut versucht, in der Hoffnung, weitere Hinweise zu erhalten. Da fiel mir auf, dass nicht nur 310 Datensätze fehlten, sondern dass der letzte Datensatz auch unvollständig war.
65030 adam@gmail.com, gmail, 2023-03-17 15:04:05.000 65031 jac@hotmail.com, hotmail, 2023-03-17 15:04:05.000 65032 nancy@xyz.com, hotmail, 2023-03-
Das war ein Fortschritt – ich konnte das Problem jetzt eingrenzen und mich auf w.Write(newRecord(domain, elm)) konzentrieren, insbesondere auf die Methode w.Write(...). Ich habe die Dokumentation überprüft und den Grund gefunden:
... Schreibvorgänge werden gepuffert, daher muss schließlich [Writer.Flush] aufgerufen werden, um sicherzustellen, dass der Datensatz in den zugrunde liegenden io.Writer geschrieben wird ...
Ich hatte vergessen, w.Flush() aufzurufen. Dies war sinnvoll, da der CSV-Writer aus Performance-Sicht Schreibvorgänge puffert, anstatt bei jedem Aufruf von w.Write() E/A-Vorgänge auszuführen. Durch das Puffern von Daten wird die E/A-Last reduziert und der Aufruf von w.Flush() am Ende stellt sicher, dass alle verbleibenden Daten im Puffer in die Datei geschrieben werden.
Hier ist der korrigierte Code:
... f, err := os.Create(fName) if err != nil { log.Println("Unable to create file", err) return } defer f.Close() w := csv.NewWriter(f) defer w.Flush() // Add header header := []string{"email", "provider", "added_on"} ...
Zur Bestätigung habe ich den bufio.go-Quellcode überprüft und festgestellt, dass die Standardpuffergröße 4 KB beträgt. In der WriteRune(...)-Methode sehen Sie, dass sie Flush immer dann aufruft, wenn der Puffer sein Limit erreicht.
Das ist alles! Ich hoffe, die Lektüre hat Ihnen gefallen. Ich neige dazu, viel aus Fehlern zu lernen – seien es meine eigenen oder die anderer. Auch wenn es keine sofortige Lösung gibt, hilft mir die Entdeckung eines falschen Ansatzes, ähnliche Fallstricke in Zukunft zu vermeiden. Deshalb wollte ich diese Erfahrung teilen!
Das obige ist der detaillierte Inhalt vonDas Geheimnis fehlender Datensätze: Debuggen einer JSON-zu-CSV-Transformation in Go. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!