Quelle est la différence entre ResponseWriter.Écrire et io.WriteString?
J'ai vu trois manières d'écrire le contenu de la réponse HTTP:
func Handler(w http.ResponseWriter, req *http.Request) {
io.WriteString(w, "blabla.\n")
}
Et:
func Handler(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("blabla\n"))
}
Il y a également:
fmt.Fprintf(w, "blabla")
Quelle est la différence entre eux? Qui est préférée à l'utilisation?
Vous devez vous connecter pour publier un commentaire.
io.Writer
Un flux de sortie représente une cible à laquelle vous pouvez écrire des séquence(s) d'octets. Dans cette est capturé par le général
io.L'écrivain
interface:Tout ce qui a cette seule
Write()
méthode peut être utilisée comme une sortie, par exemple un fichier sur votre disque dur (os.Fichier
), d'une connexion réseau (net.Conn
) ou un tampon en mémoire (octets.Tampon
).La
http.ResponseWriter
qui est utilisé pour configurer la réponse HTTP et envoie les données vers le client est également uneio.Writer
, les données que vous voulez envoyer (le corps de la réponse) est monté en appelant (pas nécessairement juste une fois)ResponseWriter.Write()
(qui est de mettre en œuvre le généralio.Writer
). Ceci est la seule garantie que vous avez sur la mise en œuvre de lahttp.ResponseWriter
interface (concernant l'envoi de l'organisme).WriteString()
Maintenant sur
WriteString()
. Souvent nous voulons écrire des données textuelles à unio.Writer
. Oui, on peut le faire simplement en convertissant lestring
à un[]byte
, par exemplequi fonctionne comme prévu. Cependant c'est une opération très fréquente et il est donc "en général" méthode acceptée pour ce capturé par les
io.StringWriter
interface (disponible depuis 1.12 Go, avant qu'il a été désexporter):Cette méthode donne la possibilité d'écrire un
string
de la valeur au lieu d'une[]byte
. Donc, si quelque chose (qui implémente égalementio.Writer
) met en œuvre cette méthode, vous pouvez tout simplement passer àstring
valeurs sans[]byte
de conversion. Cela semble être un mineur de simplification dans le code, mais c'est plus que cela. La conversion d'unstring
à[]byte
a faire une copie de lastring
contenu (parce questring
valeurs immuables Allez lire plus à ce sujet ici: golang: []byte(string) vs []byte(*string)), donc il y a certains frais généraux, qui devient perceptible si l'string
est plus "grand" et/ou que vous avez à faire à de nombreuses reprises.Selon la nature et les détails de mise en œuvre d'un
io.Writer
, il peut être possible d'écrire le contenu d'unstring
sans convertir[]byte
et d'éviter ainsi l'mentionnés ci-dessus les frais généraux.Comme un exemple, si un
io.Writer
est quelque chose qui écrit dans un tampon en mémoire (bytes.Buffer
est un exemple), il peut utiliser le builtincopier()
fonction:La
copy()
peut être utilisé pour copier le contenu (en octets) d'unstring
dans un[]byte
sans conversion de lastring
à[]byte
, par exemple:Maintenant, il y a une "utilité" de la fonction
io.WriteString()
qui écrit unstring
dans unio.Writer
. Mais il le fait en vérifiant d'abord si l' (type dynamique de l') passéio.Writer
a unWriteString()
méthode, et si oui, qui sera utilisé (dont la mise en œuvre est probablement plus efficace). Si le passéio.Writer
n'a pas cette méthode, alors que le général convertir-à-octet-tranche-et-écrire-que méthode sera utilisée comme un "repli".Vous pourriez penser que ce
WriteString()
ne prévalent dans le cas de la mémoire tampon, mais ce n'est pas vrai. Les réponses de requêtes web sont également souvent tamponnée (à l'aide d'un tampon en mémoire), de sorte qu'il peut améliorer les performances en cas dehttp.ResponseWriter
trop. Et si vous regardez à la mise en œuvre dehttp.ResponseWriter
: c'est le désexporter typehttp.response
(server.aller
actuellement en ligne n ° 308), qui n'en œuvreWriteString()
(actuellement la ligne #1212) de sorte qu'il n'impliquent amélioration.Dans l'ensemble, chaque fois que vous écrivez
string
valeurs recommandées pour l'utilisation deio.WriteString()
qu'il peut être plus efficace (plus rapide).fmt.Fprintf()
Vous devriez considérer cela comme un moyen pratique et facile pour ajouter plus de mise en forme les données que vous voulez écrire, en échange d'un peu moins performant.
Donc utiliser
de l'esf.Fprintf()
si vous voulez formatéstring
créé dans la voie de la facilité, par exemple:Qui sera
string
être écrit:Une chose que vous ne devez pas oublier:
fmt.Fprintf()
s'attend à un chaîne de format, de sorte qu'il sera analysée et non pas écrite comme à la sortie. Comme un exemple rapide:Vous attendons à ce que
"100 %%"
serait écrit à la sortie (avec 2%
caractères), mais un seul sera envoyée dans la chaîne de format%
est un caractère spécial et%%
ne fait qu'un%
dans la sortie.Si vous voulez juste écrire un
string
à l'aide de lafmt
package, utilisezde l'esf.Fprint()
qui ne nécessite pas un formatstring
:Un autre avantage de l'utilisation de la
fmt
paquet est que vous pouvez écrire les valeurs des autres types de trop, pas seulementstring
s, par exemple(Bien sûr, les règles de comment convertir une valeur en une
string
–et à la série d'octets à la fin–est bien défini, dans la doc de lafmt
package.)Pour de "simples" formaté sorties de la
fmt
paquet pourrait être OK. Pour des complexes de documents de sortie n'envisager l'utilisation de latext/template
(pour le texte) ethtml/template
(lorsque la sortie est en HTML).Passant /remise
http.ResponseWriter
Pour être complet, il convient de mentionner que, souvent, le contenu que vous souhaitez envoyer la réponse web est généré par "quelque chose" qui prend en charge le "streaming" le résultat. Un exemple peut être une réponse JSON, qui est généré à partir d'une structure ou d'une carte.
Dans de tels cas, il est souvent plus efficace de passer la main au-dessus de votre
http.ResponseWriter
qui est unio.Writer
à ce quelque chose si elle prend en charge l'écriture du résultat dans unio.Writer
à la volée.Un bon exemple de cela est de générer des réponses JSON. Bien sûr, vous pourriez ranger un objet en JSON avec
json.Maréchal()
, qui vous renvoie un octet tranche, qui vous pouvez tout simplement envoyer en appelantResponseWriter.Write()
.Cependant, il est plus efficace de laisser les
json
package de savoir que vous avez unio.Writer
, et, finalement, vous voulez envoyer le résultat à qui. De cette façon, il est inutile de générer d'abord le texte JSON dans un tampon, que vous venez d'écrire dans votre réponse avant de le jeter. Vous pouvez créer un nouveaujson.Codeur
en appelantjson.NewEncoder()
à laquelle vous pouvez passer votrehttp.ResponseWriter
comme unio.Writer
, et en appelantCodeur.Encode()
après qui va écrire directement le résultat JSON dans votre réponse écrivain.Un inconvénient ici est que si la génération de la réponse JSON échoue, vous pourriez avoir un partiellement envoyé /commis de réponse, que vous ne prenez le dos. Si c'est un problème pour vous, vous n'avez pas vraiment d'autre choix que la génération de la réponse dans un tampon, et si marshaling de succès, alors vous pouvez écrire la réponse complète à la fois.
write
est suffisante, car c'est de l'octet?json.Marshal()
et simplementw.Write()
le résultat, ou vous pouvez créer un nouveaujson.Encoder
habillage de laResponseWriter
de sous-jacent / cible de l'écrivain. Il dépend de la façon dont vous souhaitez gérer les erreurs, en tant que regroupement d'abord vous donne plus d'options sur la manière de procéder, à l'opposé dejson.Encoder
auquel cas la réponse est peut-être déjà écrit lorsqu'une erreur est détectée.It also depends how you want to handle errors, as marshaling first gives you more options how to proceed, opposed to json.Encoder in which case response may already be written when an error is detected.
Pourriez-vous expliquer un peu ou donner un exemple?json.Marshal()
, il tente d'abord de maréchal de la valeur, et renvoie le résultat sous la forme d'un[]byte
et unerror
si marshaling a échoué. À ce stade, rien n'est écrit à l'ResponseWriter
, donc si il y avait une erreur, vous pouvez même choisir de renvoyer une page d'erreurs HTML (type de contenu).json.Encoder
et que vous appelezEncoder.Encode()
, il tente d'écrire des données JSON à laResponseWriter
et renvoie unerror
si il y en avait un. Mais à partir du moment où une erreur est renvoyée,Encode()
peut-être déjà écrit quelques données partielles pour la réponse (ce qui implique d'en-têtes d'être commis): vous ne pouvez pas "reprendre" la partie écrite de données et vous ne pouvez pas modifier les en-têtes HTTP en ce moment. Si vous souhaitez modifier la réponse en ce moment: vous êtes foutu.Comme vous pouvez le voir à partir de ici(ResponseWriter), que c'est une interface avec
Write([]byte) (int, error)
méthode.Donc dans
io.WriteString
etfmt.Fprintf
prennent Auteur comme 1er argument qui est aussi une interface d'emballageWrite(p []byte) (n int, err error)
méthodeAinsi, lorsque vous appelez io.WriteString(w,"bla") vérifiez ici
ou de l'esf.Fprintf(w, "blabla") vérifiez ici
vous êtes simplement en appelant la Méthode d'Écriture indirectement comme vous êtes de passage à
ResponseWriter
variable dans les deux méthodes.Si juste pourquoi ne pas l'appeler directement en utilisant
w.Write([]byte("blabla\n"))
. J'espère que vous avez votre réponse.PS: il y a aussi une autre façon de l'utiliser, si vous voulez envoyer en réponse JSON.
Write
?