2015-09-28 34 views

Odpowiedz

13

Ogólna koncepcja jest taka, że ​​gdy funkcja (lub metody) ma wielu zwracają wartości jednego będąc error, błąd powinien być sprawdzane jako pierwsze i kontynuowane, jeśli błąd wynosi nil. Funkcje powinny zwracać wartości zerowe dla innych (bez błędów) wartości, jeśli istnieje error. Jeśli funkcja zachowuje się inaczej, powinna być udokumentowana. http.Get() nie dokumentuje takich odchyleń.

Więc to powinno być traktowane tak:

res, err := http.Get(url) 
if err != nil { 
    log.Printf("Error: %s\n", err) 
    return 
} 

defer res.Body.Close() 
// Read/work with body 

Uwagi:

Jak JimB potwierdza też, jeśli nie- nil zwracany jest błąd, nawet jeśli odpowiedź nie jest - nil, nie musimy tego zamykać. W przypadku błędu przekierowania odpowiedź inna niż nil może zawierać kontekst i dodatkowe informacje o tym, gdzie po przekierowaniu nie powiodło się. Zobacz szczegóły poniżej:

http.Get() wyróżnieniem ogólnej koncepcji „przez większość czasu”: zwraca nil odpowiedź, jeśli wystąpi błąd:

return nil, someError 

Jednak sprawdzanie client.go, metoda unexported Client.doFollowingRedirects(), obecnie linia # 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 
} 

Więc ze względu na wsteczną kompatybilność problemu może powrócić niebędącą nil odpowiedź i niebędącą nil błąd w tym samym czasie, f przekierowanie nie działa.

Z drugiej strony próba wywołania resp.Body.Close(), jeśli resp jest nil spowoduje panikę run-time.

Więc jeśli chcemy, aby zamknąć ciało reakcji w tym przypadku, może wyglądać następująco (może być zamknięty tylko wtedy resp nie jest 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 
} 

czyli

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 

The dokument nr http.Response gwarantuje, że Response.Body nie będzie nil, nawet jeśli nie ma danych o odpowiedzi:

// 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. 
+4

Jeśli kiedykolwiek otrzymasz ciało odpowiedzi wymagające zamknięcia w wyniku błędu, jest to błąd, który należy złożyć. W takim przypadku powinieneś mieć puste noop bliżej ciała, które tylko tam, aby zamknąć, nie panikuj. – JimB

+0

@JimB Tak też myślałem. Dzięki za potwierdzenie. Dokona edycji odpowiedzi. – icza

+3

Poszedłem i podwoiłem sprawdzanie kodu klienta, aw jednym przypadku, gdy błąd przekierowania zwraca odpowiedź, ciało zostało już zamknięte, a połączenie zwolnione. Chociaż to nie boli, nigdy nie powinno być potrzeby "odraczania resp.Body.Close()" po błędzie klienta. – JimB