Réponses:
É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 effectuant string
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 ton io.ReaderCloser
nom rc
, j'écrirais,
if b, err := ioutil.ReadAll(rc); err == nil {
return string(b)
} ...
buf.ReadFrom()
également lire le flux entier jusqu'à EOF.
ioutil.ReadAll()
et ça enveloppe simplement un bytes.Buffer
's ReadFrom
. Et la String()
méthode du tampon est un simple enroulement autour du casting string
- donc les deux approches sont pratiquement les mêmes!
data, _ := ioutil.ReadAll(response.Body)
fmt.Println(string(data))
Le moyen le plus efficace serait de toujours utiliser à la []byte
place de string
.
Au cas où vous auriez besoin d'imprimer les données reçues de io.ReadCloser
, le fmt
package peut gérer []byte
, mais ce n'est pas efficace car l' fmt
implémentation sera convertie en interne []byte
en string
. Afin d'éviter cette conversion, vous pouvez implémenter l' fmt.Formatter
interface pour un type comme type ByteSlice []byte
.
[]byte
à string
est raisonnablement rapide, mais la question était de savoir "le moyen le plus efficace". Actuellement, le runtime Go allouera toujours un nouveau string
lors de la conversion []byte
en string
. 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.
func copyToString(r io.Reader) (res string, err error) {
var sb strings.Builder
if _, err = io.Copy(&sb, r); err == nil {
res = sb.String()
}
return
}
var b bytes.Buffer
b.ReadFrom(r)
// b.String()
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.