В golang у меня есть некоторые http ответы, и я иногда забываю звонить:
resp.Body.Close()
Что происходит в этом случае? будет утечка памяти? Также это безопасный вставить defer resp.Body.Close()
сразу после получения объекта ответа?
client := http.DefaultClient
resp, err := client.Do(req)
defer resp.Body.Close()
if err != nil {
return nil, err
}
Что, если существует ошибка, могло resp
или resp.Body
быть нолем?
Сначала дескриптор никогда не закрывается как упомянутые выше вещи.
И кроме того, golang будет кэшировать соединение (использующий persistConn
структура для обертывания) для многократного использования его, если DisableKeepAlives
будет ложь.
В golang после использования client.Do
метод, движение выполнит метод goroutine readLoop
как один из шага.
Так в golang http transport.go
, pconn(persistConn struct)
не будет помещен в idleConn
канал, пока req не отменил в readLoop
метод, и также этот goroutine (readLoop
метод) будет заблокирован, пока req не отменил.
Вот код показ его.
, Если Вы хотите знать больше, необходимо видеть readLoop
метод.
Если Response.Body
не будет закрыт с Close()
метод, чем, ресурсы, связанные с fd, не будут освобождены. Это - утечка ресурсов.
Response.Body
От источник ответа :
Это - обязанность вызывающей стороны закрыть Тело.
, Таким образом, нет никаких финализаторов, связанных с объектом и он должен быть закрыт явно.
На ошибке, любой Ответ может быть проигнорирован. Ненулевой Ответ с ненулевой ошибкой только происходит, когда CheckRedirect перестал работать, и даже затем возвращенный Ответ. Тело уже закрывается.
resp, err := http.Get("http://example.com/")
if err != nil {
// Handle error if error is non-nil
}
defer resp.Body.Close() // Close body only if response non-nil
См. https://golang.org/src/net/http/client.go
, "Когда допускают ошибку, ноль, resp всегда содержит неноль resp. Тело".
, но они не говорят, когда допускают ошибку! = ноль, resp всегда является нолем. Они продолжают:
, "Если resp. Тело не закрывается, базовый RoundTripper Клиента (обычно Транспорт) не может снова использовать персистентное соединение TCP к серверу для последующего "активного" запроса".
, Таким образом, я обычно решал проблему как это:
client := http.DefaultClient
resp, err := client.Do(req)
if resp != nil {
defer resp.Body.Close()
}
if err != nil {
return nil, err
}