Bytes in einen Stream verwandeln: io.Reader aus []byte in Go

Online Python-Trainer für Anfänger

Lernen Sie Python einfach ohne theoretische Überlastung. Lösen Sie praktische Aufgaben mit automatischer Überprüfung und schreiben Sie Code direkt im Browser.

Kurs starten

Einleitung: Warum müssen Sie möglicherweise Bytes in einen Stream umwandeln?

\n\n

Stellen Sie sich folgende Situation vor: Sie haben einen großartigen Dienst in Go geschrieben, der Daten von einer externen API abruft. Die Antwort kommt als Byte-Array ([]byte). Das wäre ja noch in Ordnung, aber das Problem ist, dass die nächste Funktion in Ihrer Pipeline als Eingabe kein Byte-Slice, sondern ein io.Reader-Interface erwartet. Was tun? In Panik geraten? Das Rad neu erfinden? Nein! Es reicht, sich an bytes.NewReader zu erinnern.

\n\n

Diese Frage ist eine der beliebtesten auf Stack Overflow (tausende Aufrufe!). Und das zu Recht. In Go ist das Konzept von io.Reader die Grundlage für die Arbeit mit Datenströmen: Dateien, Netzwerkverbindungen, HTTP-Antworten und natürlich auch nur Bytes im Arbeitsspeicher. Wenn Sie ein Go-Anfänger sind, werden Sie früher oder später auf diese Hürde stoßen. Lassen Sie uns herausfinden, wie Sie diese elegant und effizient umgehen können.

\n\n

In diesem Artikel geben wir nicht nur den trockenen Befehl „verwende bytes.NewReader“. Wir erklären, warum das funktioniert, welche Alternativen es gibt und zeigen reale Beispiele aus der Praxis. Los geht's!

\n\n

Theorie: Was ist io.Reader und wozu wird er verwendet?

\n\n

Bevor wir konvertieren, erinnern wir uns daran, was io.Reader ist. Es ist ein Interface, das in der Go-Standardbibliothek definiert ist:

\n\n
type Reader interface {\n    Read(p []byte) (n int, err error)\n}
\n\n

So einfach und genial. Jede Struktur, die eine Methode Read(p []byte) (int, error) hat, erfüllt automatisch das io.Reader-Interface. Dies ermöglicht es, universellen Code zum Lesen von Daten aus jeder Quelle zu schreiben: Datei, Socket, Zeichenkette, Byte-Slice.

\n\n

Warum ist das großartig? Weil Sie eine Funktion schreiben können, die JSON, XML parst oder einfach Daten kopiert, ohne sich darum kümmern zu müssen, woher sie kommen. Sie brauchen nur einen io.Reader. Das ist eine Abstraktion eines Streams.

\n\n

Aber was tun, wenn Sie bereits Daten im Speicher haben (z. B. []byte)? Sie benötigen ein Objekt, das sich als Stream „ausgibt“, aber dabei aus Ihrem Slice liest. Hier kommt bytes.NewReader ins Spiel.

\n\n

Die Hauptmethode: bytes.NewReader

\n\n

Dies ist der einfachste und korrekteste Weg. Die Funktion bytes.NewReader nimmt ein []byte entgegen und gibt einen Zeiger auf die Struktur bytes.Reader zurück, die io.Reader (sowie io.ReadSeeker, io.WriterTo und andere nützliche Interfaces) implementiert.

\n\n

Beispiel 1: Grundlegende Verwendung

\n\n
package main\n\nimport (\n    "bytes"\n    "fmt"\n    "io"\n    "log"\n)\n\nfunc main() {\n    // Unser ursprüngliches Byte-Slice\n    data := []byte("Hallo, Welt! Das sind Bytes.")\n\n    // Erstellen eines Readers aus dem Byte-Slice\n    reader := bytes.NewReader(data)\n\n    // Daten aus dem Reader in einen Puffer lesen\n    buf := make([]byte, 10) // 10 Bytes auf einmal lesen\n    for {\n        n, err := reader.Read(buf)\n        if err != nil {\n            if err == io.EOF {\n                break // Lesen beendet\n            }\n            log.Fatal(err)\n        }\n        fmt.Printf("Gelesen %d Bytes: %s\\n", n, buf[:n])\n    }\n    // Output:\n    // Gelesen 10 Bytes: Hallo, Wel\n    // Gelesen 10 Bytes: t! Das sin\n    // Gelesen 6 Bytes: d Bytes.\n}
\n\n

Beachten Sie: bytes.Reader verhält sich wie ein echter Stream. Wenn die Daten zu Ende sind, gibt er io.EOF zurück. Alles fair.

\n\n

Beispiel 2: Verwendung mit io.Copy

\n\n

Das häufigste Szenario ist das Kopieren von Bytes an einen anderen Ort (in eine Datei, in eine HTTP-Antwort). Dafür ist io.Copy ideal geeignet:

\n\n
package main\n\nimport (\n    "bytes"\n    "fmt"\n    "io"\n    "os"\n)\n\nfunc main() {\n    data := []byte("Diese Daten in eine Datei speichern.")\n    reader := bytes.NewReader(data)\n\n    // Datei erstellen\n    file, err := os.Create("output.txt")\n    if err != nil {\n        panic(err)\n    }\n    defer file.Close()\n\n    // Vom Reader in die Datei kopieren\n                

Blogs

Buchempfehlungen