J'ai un io.ReadCloser
objet (à partir d'un http.Response
objet).
Quel est le moyen le plus efficace de convertir le flux entier en un objet string
?
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 manière appropriée (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 en tant que mécanisme de protection. Les cordes sont immuables. Si vous pouviez convertir un octet [] en chaîne, vous pourriez en modifier le contenu. Cependant, go vous permet de désactiver les mécanismes de sécurité de type à l'aide du package non sécurisé. Utilisez le paquet dangereux à vos risques et périls. Espérons que le nom 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 ce que cela fait, c'est de tromper le système de typage 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 ça cher et cela ne vaut pas le mal d'être dangereux. Si la chaîne est trop grande pour faire une copie, vous ne devriez pas en faire une chaîne.
Les réponses à ce jour n'ont pas abordé la partie "flux complet" de la question. Je pense que la bonne façon de faire ceci est ioutil.ReadAll
. Avec votre io.ReaderCloser
Nommé rc
, j’écrirais,
if b, err := ioutil.ReadAll(rc); err == nil {
return string(b)
} ...
Le moyen le plus efficace serait de toujours utiliser []byte
au lieu de string
.
Au cas où vous auriez besoin d’imprimer les données reçues du io.ReadCloser
, le package fmt
peut gérer []byte
, mais cela n’est pas efficace car l’implémentation de fmt
convertira en interne []byte
à string
. Pour éviter cette conversion, vous pouvez implémenter le fmt.Formatter
interface pour un type comme type ByteSlice []byte
.
data, _ := ioutil.ReadAll(response.Body)
fmt.Println(string(data))
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
}
J'aime le bytes.Buffer struct. Je vois qu'il a ReadFrom et String méthodes. Je l'ai utilisé avec un octet [] mais pas un io.Reader.