In Go habe ich einige http-Antworten und vergesse manchmal anzurufen:
resp.Body.Close()
Was passiert in diesem Fall? Wird es einen Speicherverlust geben? Ist es auch sicher, defer resp.Body.Close()
sofort nach Erhalt des Antwortobjekts einzugeben?
client := http.DefaultClient
resp, err := client.Do(req)
defer resp.Body.Close()
if err != nil {
return nil, err
}
Was ist, wenn ein Fehler vorliegt, der Null sein könnte resp
oder resp.Body
sein könnte ?
Antworten:
Es ist ein Ressourcenleck. Die Verbindung wird nicht wiederverwendet und kann offen bleiben. In diesem Fall wird der Dateideskriptor nicht freigegeben.
Nein, folgen Sie dem Beispiel in der Dokumentation und schließen Sie es sofort, nachdem Sie den Fehler überprüft haben.
Aus der
http.Client
Dokumentation:quelle
io.LimitReader
. Normalerweise verwende ich ein relativ kleines Limit, da es schneller ist, eine neue Verbindung herzustellen, wenn die Anfrage zu groß ist.Wenn
Response.Body
nicht mitClose()
Methode geschlossen wird, werden Ressourcen, die einem fd zugeordnet sind, nicht freigegeben. Dies ist ein Ressourcenleck.Schließen
Response.Body
Aus der Antwortquelle :
Es sind also keine Finalizer an das Objekt gebunden und es muss explizit geschlossen werden.
Fehlerbehandlung und verzögerte Bereinigung
quelle
Zunächst wird der Deskriptor nie geschlossen, wie oben erwähnt.
Und außerdem speichert Golang die Verbindung zwischen (wobei
persistConn
struct zum Umbrechen verwendet wird ), um sie wiederzuverwenden , wenn sieDisableKeepAlives
falsch ist.In der Golang-After-Use-
client.Do
Methode führt go die Goroutine-readLoop
Methode als einen der Schritte aus.In golang http
transport.go
wird apconn(persistConn struct)
erst dann in denidleConn
Kanal eingefügt , wenn die Anforderung in derreadLoop
Methode abgebrochen wurde , und auch diese Goroutine (readLoop
Methode) wird blockiert, bis die Anforderung abgebrochen wird.Hier ist der Code , der es zeigt.
Wenn Sie mehr wissen möchten, müssen Sie die
readLoop
Methode sehen.quelle
Siehe https://golang.org/src/net/http/client.go.
"Wenn err null ist, enthält resp immer einen Nicht-null resp.Body."
aber sie sagen nicht, wenn err! = nil, resp ist immer nil. Sie fahren fort:
"Wenn resp.Body nicht geschlossen ist, kann der zugrunde liegende RoundTripper des Clients (normalerweise Transport) eine dauerhafte TCP-Verbindung zum Server möglicherweise nicht für eine nachfolgende" Keep-Alive "-Anforderung wiederverwenden."
Daher habe ich das Problem normalerweise folgendermaßen gelöst:
quelle
Könnte mir jemand sagen, wenn die Verbindung nicht ohne Schließen wiederverwendet werden kann, warum die Ausgabe von
ist
quelle