J'ai un io.ReadCloser
objet (d'un http.Response
objet).
Quelle est la manière la plus efficace de convertir l'intégralité du flux en string
objet?
ÉDITER:
Depuis la 1.10, strings.Builder existe. Exemple:
buf := new(strings.Builder)
n, err := io.Copy(buf, r)
// check errors
fmt.Println(buf.String())
INFORMATIONS DÉPASSÉES CI-DESSOUS
La réponse courte est que cela ne sera pas efficace car la conversion en chaîne nécessite de faire une copie complète du tableau d'octets. Voici la bonne façon (non efficace) de faire ce que vous voulez:
buf := new(bytes.Buffer)
buf.ReadFrom(yourReader)
s := buf.String() // Does a complete copy of the bytes in the buffer.
Cette copie est faite comme un mécanisme de protection. Les chaînes sont immuables. Si vous pouviez convertir un octet [] en chaîne, vous pourriez changer le contenu de la chaîne. Cependant, go vous permet de désactiver les mécanismes de sécurité de type à l'aide du package unsafe. Utilisez l'emballage dangereux à vos propres risques. Espérons que le nom à lui seul est un avertissement suffisant. Voici comment je le ferais en utilisant unsafe:
buf := new(bytes.Buffer)
buf.ReadFrom(yourReader)
b := buf.Bytes()
s := *(*string)(unsafe.Pointer(&b))
Voilà, vous avez maintenant converti efficacement votre tableau d'octets en chaîne. En réalité, tout cela ne fait que tromper le système de types en l'appelant une chaîne. Il y a quelques mises en garde à cette méthode:
Mon conseil est de s'en tenir à la méthode officielle. Faire une copie n'est pas si cher et cela ne vaut pas les maux de dangereux. Si la chaîne est trop volumineuse pour faire une copie, vous ne devez pas en faire une chaîne.
strings.Builder
fait cela efficacement en garantissant que le sous-jacent[]byte
ne fuit jamais et en effectuantstring
une conversion sans copie d'une manière qui sera prise en charge à l'avenir. Cela n'existait pas en 2012. La solution de @ dimchansky ci-dessous est la bonne depuis Go 1.10. Veuillez envisager une modification!Les réponses jusqu'à présent n'ont pas abordé la partie "flux entier" de la question. Je pense que la bonne façon de faire est
ioutil.ReadAll
. Avec tonio.ReaderCloser
nomrc
, j'écrirais,la source
buf.ReadFrom()
également lire le flux entier jusqu'à EOF.ioutil.ReadAll()
et ça enveloppe simplement unbytes.Buffer
'sReadFrom
. Et laString()
méthode du tampon est un simple enroulement autour du castingstring
- donc les deux approches sont pratiquement les mêmes!la source
Le moyen le plus efficace serait de toujours utiliser à la
[]byte
place destring
.Au cas où vous auriez besoin d'imprimer les données reçues de
io.ReadCloser
, lefmt
package peut gérer[]byte
, mais ce n'est pas efficace car l'fmt
implémentation sera convertie en interne[]byte
enstring
. Afin d'éviter cette conversion, vous pouvez implémenter l'fmt.Formatter
interface pour un type commetype ByteSlice []byte
.la source
[]byte
àstring
est raisonnablement rapide, mais la question était de savoir "le moyen le plus efficace". Actuellement, le runtime Go allouera toujours un nouveaustring
lors de la conversion[]byte
enstring
. La raison en est que le compilateur ne sait pas comment déterminer si le[]byte
sera modifié après la conversion. Il y a de la place pour les optimisations du compilateur ici.la source
la source
J'aime la structure bytes.Buffer . Je vois qu'il a des méthodes ReadFrom et String . Je l'ai utilisé avec un octet [] mais pas avec un io.Reader.
la source