Что могло произойти, если я не закрываю ответ. Тело в golang?

В 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 быть нолем?

62
задан 20 October 2015 в 16:49

3 ответа

Сначала дескриптор никогда не закрывается как упомянутые выше вещи.

И кроме того, golang будет кэшировать соединение (использующий persistConn структура для обертывания) для многократного использования его, если DisableKeepAlives будет ложь.

В golang после использования client.Do метод, движение выполнит метод goroutine readLoop как один из шага.

Так в golang http transport.go, pconn(persistConn struct) не будет помещен в idleConn канал, пока req не отменил в readLoop метод, и также этот goroutine (readLoop метод) будет заблокирован, пока req не отменил.

Вот код показ его.

, Если Вы хотите знать больше, необходимо видеть readLoop метод.

1
ответ дан 31 October 2019 в 14:19

Если 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
8
ответ дан 31 October 2019 в 14:19

См. 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 
}
1
ответ дан 31 October 2019 в 14:19

Другие вопросы по тегам:

Похожие вопросы: