webentwicklung-frage-antwort-db.com.de

So lesen Sie mehrere Male von demselben io.Reader

Ich möchte request.Body(type io.ReadCloser) verwenden, das ein Bild enthält.

Ich möchte ioutil.ReadAll() nicht verwenden, da ich diesen Body direkt in die Datei schreiben und auch dekodieren möchte. Daher möchte ich nur den Verweis auf den Inhalt verwenden, um ihn an weitere Funktionsaufrufe weiterzuleiten.

Ich habe versucht, mehrere Instanzen des Readers zu erstellen (siehe unten)

package main

import (
    "io/ioutil"
    "log"
    "strings"
)


func main() {
    r := strings.NewReader("some io.Reader stream to be read\n")
    a := &r
    b := &r
    log.Println(ioutil.ReadAll(*a))
    log.Println(ioutil.ReadAll(*b))

}

aber beim zweiten Aufruf ergibt sich immer nil.

Bitte helfen Sie mir, wie kann ich mehrere separate Referenzen für denselben Leser übergeben?

21
Abhishek Soni

io.Reader wird wie ein Stream behandelt. Aus diesem Grund können Sie es nicht zweimal lesen. Stellen Sie sich eine eingehende TCP Verbindung vor. Sie können die eingehenden Daten nicht zurückspulen.

Aber Sie können das io.TeeReader um den Stream zu duplizieren:

package main

import (
    "bytes"
    "io"
    "io/ioutil"
    "log"
    "strings"
)

func main() {
    r := strings.NewReader("some io.Reader stream to be read\n")
    var buf bytes.Buffer
    tee := io.TeeReader(r, &buf)

    log.Println(ioutil.ReadAll(tee))
    log.Println(ioutil.ReadAll(&buf)) 
}

Beispiel am Go Playground

40
TheHippo

Wenn Sie ReadAll aufrufen, wird der Puffer geleert, sodass der zweite Aufruf immer nichts zurückgibt. Sie können das Ergebnis von ReadAll speichern und in Ihren Funktionen wiederverwenden. Beispielsweise:

bytes, _ := ioutil.ReadAll(r);
log.Println(string(bytes))
4
laurent

@TheHippo Antwort ist richtig Ich wollte das nur hinzufügen (konnte es aber nicht hinzufügen, weil ich nur 49 Reputation habe :(): Es ist wichtig, dass Sie den TeeReader zuerst verwenden und nachdem Sie den Puffer, in den die Informationen kopiert werden, ansonsten den zweiten Der Puffer ist leer.

1
mrclx

Technisch gesehen können Sie auf einem Lesegerät nicht mehrere Male lesen.

  • Auch wenn Sie andere Referenzen erstellen aber
  • wenn Sie einmal lesen, wird dasselbe Objekt von allen Referenzen referenziert.
  • sie können also den Inhalt lesen und in einer Variablen speichern.
  • Verwenden Sie diese Variable dann so oft, wie Sie möchten.

Dies wird zweimal gedruckt.

package main

import (
    "io/ioutil"
    "log"
    "strings"
)

func main() {
    r := strings.NewReader("some io.Reader stream to be read\n")
    stringData, _ := ioutil.ReadAll(r)
    log.Println(stringData)
    log.Println(stringData)
}
1
Vijay Gurunanee