Почему вы должны закрыть тело запроса, как только вы его проверили? [Дубликат]

Я нашел способ конвертировать временную метку Unix в дату Excel.

$date_time = "2013-11-01 00:00:00";
$date_time_plus_one = strtotime($date_time . ' +1 day');
$str_date = strtotime(date('Y-m-d', $date_time_plus_one));
$excel_date = intval(25569 + $str_date / 86400);

echo 'php actual date time : ' . $date_time . '<br>';
echo 'add one day : ' . $date_time_plus_one . '<br>';
echo 'excel Number DATEVALUE : ' . $excel_date . '<br>';

секунд в день: 86400, 25569 дней между 30 декабря 1899 года и 01 января 1970 года. Таким образом, это результат .

php фактическое время: 2013-11-01 00:00:00

добавить один день: 1383330600

excel Number DATEVALUE: 41579

27
задан Daniel Robinson 20 October 2015 в 13:49
поделиться

4 ответа

Что происходит в этом случае? будет ли утечка памяти?

Это утечка ресурсов. Соединение может оставаться открытым, и в этом случае дескриптор файла не будет освобожден.

Также безопасно ли вставить defer resp.Body.Close () сразу после получения объекта ответа?

Нет, следуйте примеру, приведенному в документацию и закрыть ее сразу после проверки ошибки.

client := http.DefaultClient
resp, err := client.Do(req)
if err != nil {
    return nil, err
}
defer resp.Body.Close()

Из документации http.Client:

При ошибке любой ответ можно игнорировать. Ответ на не-nil с ошибкой non-nil возникает только тогда, когда CheckRedirect терпит неудачу, и даже тогда возвращенный Response.Body уже закрыт.

39
ответ дан JimB 19 August 2018 в 18:33
поделиться
  • 1
    В соответствии с этой ссылкой все еще возможно утечка соединения с вашим кодом. Есть несколько случаев, когда ответ не равен нулю, а ошибка не равна нулю. – mmcdole 30 August 2016 в 00:35
  • 2
    @mmcdole: Это сообщение просто неправильно, и нет никакой гарантии, что он не будет паниковать, так как любой ответ возвращается при ошибке, не имеет определенного состояния. Если тело не закрыто при ошибке, то это ошибка, и ее необходимо сообщить. Вы должны зайти в официальную клиентскую документацию , в которой указывается «Об ошибке», любой ответ можно игнорировать », а не случайную запись в блоге. – JimB 30 August 2016 в 01:35
  • 3
    Спасибо за разъяснения. У меня был отчет об ошибке, зарегистрированный в моей библиотеке go, который ссылался на этот источник, и я не проверял его. Интересно, похоже, было обсуждение этого самого источника в списке рассылки golang. Похоже, что строка, на которую вы ссылались в документах, была недавно добавлена ​​в 1.6.2 - поэтому я предполагаю, что именно здесь возникла путаница для оригинального блоггера, который написал сообщение. – mmcdole 30 August 2016 в 02:09
  • 4
    @mmcdole, эта конкретная линия была добавлена ​​недавно, чтобы попытаться сделать проблему как можно более однозначной. Он всегда был задокументирован, как показано в официальных примерах. – JimB 30 August 2016 в 02:22
  • 5
    @ del-boy: Если вы ожидаете, что клиент сделает больше запросов, тогда вы должны попытаться прочитать тело, чтобы соединение можно было повторно использовать. Если вам не требуется соединение, не беспокойтесь, читая тело. Если вы читаете тело, оберните его io.LimitReader. Обычно я использую довольно небольшой предел, так как быстрее устанавливать новое соединение, если запрос слишком велик. – JimB 9 January 2017 в 15:26

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

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

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

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

Здесь это код , показывающий его.

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

1
ответ дан Alex M 19 August 2018 в 18:33
поделиться

См. https://golang.org/src/net/http/client.go «Когда err равно nil, resp всегда содержит non-nil resp.Body."

, но они не говорят, когда err! = nil, resp всегда равно нулю. Далее они говорят: «Если resp.Body не закрыт, базовый RoundTripper (обычно Transport) Клиента, возможно, не сможет повторно использовать постоянное TCP-соединение с сервером для последующего запроса« keep-alive »».

Поэтому я, как правило, решил проблему следующим образом:

client := http.DefaultClient
resp, err := client.Do(req)
if resp != nil {
   defer resp.Body.Close()
}
if err != nil {
    return nil, err 
}
0
ответ дан candita 19 August 2018 в 18:33
поделиться
  • 1
    Это неверно, и нет гарантии, что resp.Body не ноль, если есть ошибка. – JimB 2 September 2016 в 20:34
  • 2
    Спасибо @JimB. Формулировка в документах: «При ошибке, любой ответ может быть проигнорирован». Было бы более точным сказать, что «При ошибке тело ответа всегда закрыто». – candita 7 July 2017 в 14:00
  • 3
    Нет, потому что обычно нет тела ответа, которое нужно закрыть. Если вы продолжите чтение этого абзаца в документах - «Ответ на не-nil» с ошибкой non-nil возникает только тогда, когда CheckRedirect терпит неудачу, и даже тогда возвращенный Response.Body уже закрыт. & Quot; – JimB 7 July 2017 в 14:19

Если Response.Body не будет закрыт с помощью метода Close(), чем ресурсы, связанные с fd, не будут освобождены. Это утечка ресурса.

Закрытие Response.Body

Из источника ответа :

Ответственность вызывающего абонента для закрытия тела.

Таким образом, нет финализаторов, связанных с объектом, и он должен быть явно закрыт.

Обработка ошибок и отложенные очистки

При ошибке любой ответ можно игнорировать. Ответ на не-nil с ошибкой non-nil возникает только тогда, когда CheckRedirect терпит неудачу, и даже тогда возвращенный Response.Body уже закрыт.

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
4
ответ дан I159 19 August 2018 в 18:33
поделиться
  • 1
    Следует отметить, что они должны вернуться в состояние обработки ошибок. Это вызовет панику, если пользователь не вернется в обработку ошибок. – applewood 19 July 2018 в 19:25
Другие вопросы по тегам:

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