Heim > Backend-Entwicklung > Golang > Das Geheimnis fehlender Datensätze: Debuggen einer JSON-zu-CSV-Transformation in Go

Das Geheimnis fehlender Datensätze: Debuggen einer JSON-zu-CSV-Transformation in Go

Barbara Streisand
Freigeben: 2024-11-02 09:31:31
Original
1020 Leute haben es durchsucht

The Mystery of Missing Records: Debugging a JSON-to-CSV Transformation in Go

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:

  1. Öffnen Sie die JSON-Datei
  2. Parsen Sie diese JSON-Datei in eine bestimmte Struktur
  3. Schreiben Sie die Daten in eine CSV-Datei Um Ihnen zunächst eine Vorstellung zu geben: JSON ist ein Array mit 65.342 Elementen.
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
}

Nach dem Login kopieren

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-
Nach dem Login kopieren

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"}
...
Nach dem Login kopieren

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!

Quelle:dev.to
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Neueste Artikel des Autors
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage