В следующем коде также необходимо закрыть тело ответа в случае ошибки:
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.