Disons que j’ai ce gestionnaire http:
func SomeHandler(w http.ResponseWriter, r *http.Request) { data := GetSomeData() _, err := w.Write(data) }
Dois-je vérifier l’erreur renvoyée par w.Write
? Exemples J’ai vu l’ignorer et ne rien faire. De même, les fonctions telles que http.Error()
ne renvoient pas d’erreur à traiter.
C’est à vous. Mon conseil est que, à moins que la documentation de certaines méthodes / fonctions n’indique explicitement qu’elle ne retourne jamais d’erreurs non nil
(telles que bytes.Buffer.Write()
), vérifiez toujours l’erreur et le moins que vous puissiez faire est de la connecter. Si une erreur survient, elle laissera une marque sur laquelle vous pourrez enquêter si cela devenait un problème plus tard.
Cela est également vrai pour l’écriture sur http.ResponseWriter
.
Vous pourriez penser que ResponseWriter.Write()
peut uniquement renvoyer des erreurs si l’envoi des données échoue (par exemple, la connexion est fermée), mais ce n’est pas vrai. Le type concret qui implémente http.ResponseWriter
est le type http.response
non http.response
, et si vous cochez la méthode response.write()
exscope, vous verrez qu’il peut renvoyer une erreur non nil
pour un tas d’autres raisons.
Raisons pour lesquelles ResponseWriter.Write()
peut renvoyer une erreur non nil
:
http.Hijacker
(voir http.Hijacker
): http.ErrHijacked
http.ErrContentLength
http.ErrBodyNotAllowed
Même si vous ne pouvez rien faire avec l’erreur, la journalisation peut être très utile pour le débogage ultérieur de l’erreur. Par exemple, vous (ou une autre personne de la chaîne de gestionnaires) avez piraté la connexion et vous essayez de lui écrire plus tard. vous obtenez une erreur ( http.ErrHijacked
), la connexion révélera immédiatement la cause.
Si vous ne pouvez rien faire avec des erreurs occasionnelles et que ce n’est pas un “showstopper”, vous pouvez créer et utiliser une fonction simple qui effectue la vérification et la journalisation, par exemple:
func logerr(n int, err error) { if err != nil { log.Printf("Write failed: %v", err) } }
En l’utilisant:
logerr(w.Write(data))
Si vous ne voulez même pas utiliser la fonction logerr()
tout le temps, vous pouvez créer un wrapper pour http.ResponseWriter
qui le fait “automatiquement”:
type LogWriter struct { http.ResponseWriter } func (w LogWriter) Write(p []byte) (n int, err error) { n, err = w.ResponseWriter.Write(p) if err != nil { log.Printf("Write failed: %v", err) } return }
En l’utilisant:
func SomeHandler(w http.ResponseWriter, r *http.Request) { w = LogWriter{w} w.Write([]byte("hi")) }
En utilisant LogWriter
comme un wrapper autour de http.ResponseWriter
, si les écritures sur http.ResponseWriter
origine échouent, elles seront enregistrées automatiquement.
Cela a également le grand avantage de ne pas attendre une fonction de journalisation pour pouvoir appeler une valeur de votre LogWriter
“down” dans la chaîne, et tous ceux qui tenteront de l’écrire seront surveillés et consignés. s’inquiéter ou même savoir à ce sujet.
Cependant, il faut faire attention lors du passage de LogWriter
à la chaîne, car cela présente également un inconvénient: une valeur de LogWriter
pas d’autres interfaces que le http.ResponseWriter
origine pourrait également utiliser, par exemple http.Hijacker
ou http.Pusher
.
Voici un exemple sur le terrain de jeu Go qui montre cela en action, et montre également que LogWriter
ne va pas implémenter d’autres interfaces; et montre également un moyen (en utilisant 2 assertions de type “nestedes”) comment toujours extraire ce que nous voulons de LogWriter
(un http.Pusher
dans l’exemple).