The docs for net/http
have the following example:
resp, err := http.Get("http://example.com/")
if err != nil {
panic(err)
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
fmt.Printf("%s", body)
Close
returns an error
, but it is not checked. Is there something I'm missing here? The importance of checking every error is frequently emphasized in go, but I see this defer resp.Body.Close()
pattern a lot with no error checks.
Use the defer method to close the response body. This is done to make sure that the response body gets closed even in case of runtime error during reading and parsing of response.
It's important to check for errors when closing a file, even in a deferred function. Running the program confirms that the file is closed after being written.
defer resp.Body.Close() In the Go sample, if the "ParseResponse" call returns an error (and the function returns "early"), the "defer" will ensure that the response body will be closed. If the "ParseResponse" call is successful, then the "defer" will ensure that the response body will be closed.
There are two things to consider: What would you do with it if you checked it and there was an error? And, what would the side-effects be if there was an error?
In most cases, for closing a response body, the answer to both questions is... absolutely nothing. If there's nothing you'd do if there was an error and the error has no appreciable impact, there's no reason to check it.
Also note that Close()
returns an error in order to fulfill the io.Closer
interface; the function doesn't necessarily return an error. You'd need to check the source to know for sure if it has an error case.
This is a downside of using defer
It would be advised, as a responsible developer, that you check for all possible error prone points, and handle them as gracefully as you can.
Here are some of the options you can choose in handling this situation:
Do not use defer
, instead manually call close once you're done with the response's body and simply check for errors then.
Create an anonymous function that wraps the closing and error checking code. Something like this:
defer func() {
err := resp.Body.Close()
if err != nil {
log.Fatal(err)
}
}()
Avoid using
panics
in your programs. Try to handle the errors gracefully by doing something or at least logging the error.
Additional information can be found here.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With