В следующем коде также необходимо закрыть тело ответа в случае ошибки:
res, err := http.Get(url)
if err != nil {
log.Printf("Error: %s\n", err)
}
defer res.Body.Close()
В следующем коде также необходимо закрыть тело ответа в случае ошибки:
res, err := http.Get(url)
if err != nil {
log.Printf("Error: %s\n", err)
}
defer res.Body.Close()
Общая концепция заключается в том, что, когда функция (или метод) имеет множество значений возврата, одна из которых является error
, сначала следует проверить ошибку и продолжить, только если ошибка nil
. Функции должны возвращать нулевые значения для других значений (без ошибок), если есть error
. Если функция ведет себя по-другому, она должна быть документирована. http.Get()
не документирует такое отклонение.
Таким образом, его следует обрабатывать следующим образом:
res, err := http.Get(url)
if err != nil {
log.Printf("Error: %s\n", err)
return
}
defer res.Body.Close()
// Read/work with body
Примечания:
Как также подтверждает JimB, если возвращается ошибка не nil
, даже если ответ не nil
, нам не нужно его закрывать. В случае ошибки перенаправления ответ не nil
может содержать контекст и дополнительную информацию о том, где не удалось выполнить перенаправление. См. Подробности ниже:
http.Get()
отличает общее понятие "большую часть времени": он возвращает ответ nil
, если есть ошибка:
return nil, someError
Однако, проверяя client.go
, невозвращенный метод Client.doFollowingRedirects()
, в настоящее время строка # 427:
if redirectFailed {
// Special case for Go 1 compatibility: return both the response
// and an error if the CheckRedirect function failed.
// See https://golang.org/issue/3795
return resp, urlErr
}
Таким образом, из-за проблемы с обратной совместимостью он может возвращать ответ не nil
и ошибку не nil
в то же время, если сбой перенаправления.
С другой стороны, попытка вызова resp.Body.Close()
, если resp
равна nil
, приведет к панике во время выполнения.
Итак, если мы хотим закрыть тело ответа в этом случае, оно может выглядеть так (может быть закрыто, если resp
не nil
):
res, err := http.Get(url)
if err != nil {
log.Printf("Error: %s\n", err)
}
if res != nil {
defer res.Body.Close()
// Read/work with body
}
Или:
res, err := http.Get(url)
if err != nil {
log.Printf("Error: %s\n", err)
}
if res == nil {
return
}
defer res.Body.Close()
// Read/work with body
Документ http.Response
гарантирует, что Response.Body
не будет nil
, даже если нет данных ответа:
// The http Client and Transport guarantee that Body is always
// non-nil, even on responses without a body or responses with
// a zero-length body.