В следующем коде также необходимо закрыть тело ответа в случае ошибки:
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
}
Or:
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.
Но если ошибка не nil
, вам не нужно закрывать текст ответа, отличный от nil
.
defer resp.Body.Close()
после ошибки клиента.
- person JimB; 28.09.2015
err
не является nil
).
- person icza; 19.05.2016