Ich habe ein io.ReadCloser
Objekt (von einem http.Response
Objekt).
Was ist der effizienteste Weg, um den gesamten Stream in ein string
Objekt zu konvertieren ?
BEARBEITEN:
Seit 1.10 existiert strings.Builder. Beispiel:
buf := new(strings.Builder)
n, err := io.Copy(buf, r)
// check errors
fmt.Println(buf.String())
Veraltete Informationen unten
Die kurze Antwort lautet, dass dies nicht effizient ist, da für die Konvertierung in eine Zeichenfolge eine vollständige Kopie des Byte-Arrays erforderlich ist. Hier ist der richtige (nicht effiziente) Weg, um das zu tun, was Sie wollen:
buf := new(bytes.Buffer)
buf.ReadFrom(yourReader)
s := buf.String() // Does a complete copy of the bytes in the buffer.
Diese Kopie dient als Schutzmechanismus. Saiten sind unveränderlich. Wenn Sie ein [] Byte in eine Zeichenfolge konvertieren könnten, könnten Sie den Inhalt der Zeichenfolge ändern. Mit go können Sie jedoch die Typensicherheitsmechanismen mithilfe des unsicheren Pakets deaktivieren. Verwenden Sie das unsichere Paket auf eigenes Risiko. Hoffentlich ist der Name allein eine gute Warnung. So würde ich es mit unsicher machen:
buf := new(bytes.Buffer)
buf.ReadFrom(yourReader)
b := buf.Bytes()
s := *(*string)(unsafe.Pointer(&b))
Jetzt haben Sie Ihr Byte-Array effizient in einen String konvertiert. Wirklich, alles, was dies tut, ist das Typsystem dazu zu bringen, es eine Zeichenfolge zu nennen. Diese Methode weist einige Einschränkungen auf:
Mein Rat ist, sich an die offizielle Methode zu halten. Eine Kopie zu machen ist nicht so teuer und das Übel der Unsicherheit nicht wert. Wenn die Zeichenfolge zu groß ist, um eine Kopie zu erstellen, sollten Sie sie nicht zu einer Zeichenfolge machen.
strings.Builder
Dies geschieht effizient, indem sichergestellt wird, dass der Basiswert[]byte
niemals leckt, undstring
ohne Kopie auf eine Weise konvertiert wird, die in Zukunft unterstützt wird. Dies gab es 2012 nicht. Die unten stehende Lösung von @ dimchansky ist seit Go 1.10 die richtige. Bitte überlegen Sie sich eine Bearbeitung!Die Antworten haben bisher nicht den "gesamten Stream" -Teil der Frage angesprochen. Ich denke, der gute Weg, dies zu tun, ist
ioutil.ReadAll
. Mit deinemio.ReaderCloser
Namenrc
würde ich schreiben,quelle
buf.ReadFrom()
auch der gesamte Stream bis zu EOF gelesen.ioutil.ReadAll()
und es verpackt einfach abytes.Buffer
'sReadFrom
. Und dieString()
Methode des Puffers ist ein einfaches Wrap-Around-Castingstring
- die beiden Ansätze sind also praktisch gleich!quelle
Der effizienteste Weg wäre, immer
[]byte
statt zu verwendenstring
.Im Fall , dass Sie Daten aus den empfangenen drucken
io.ReadCloser
, dasfmt
kann Paket handhaben[]byte
, aber es ist nicht effizient , da diefmt
Implementierung intern konvertieren[]byte
zustring
. Um diese Konvertierung zu vermeiden, können Sie diefmt.Formatter
Schnittstelle für einen Typ wie implementierentype ByteSlice []byte
.quelle
[]byte
aufstring
ist relativ schnell, aber die Frage lautete "der effizienteste Weg". Derzeit weist die Go-Laufzeitstring
beim Konvertieren[]byte
in immer eine neue zustring
. Der Grund dafür ist, dass der Compiler nicht weiß, wie er bestimmen soll, ob der[]byte
nach der Konvertierung geändert wird. Hier gibt es Raum für Compiler-Optimierungen.quelle
quelle
Ich mag die bytes.Buffer Struktur. Ich sehe, es hat ReadFrom- und String- Methoden. Ich habe es mit einem [] Byte verwendet, aber nicht mit einem io.Reader.
quelle