I have the following code:
func Call(ctx context.Context, payload Payload) (Response, error) {
req, err := http.NewRequest(...) // Some code that creates request from payload
ctx, cancel = context.withTimeout(ctx, time.Duration(3) * time.Second)
defer cancel()
return http.DefaultClient.Do(req)
}
What would happen if I didn't put defer cancel()
in there? go vet
warned this
the cancel function returned by context.WithTimeout should be called, not discarded, to avoid a context leak
How will the context be leaked and what impact will this have? Thanks
That context is canceled if the HTTP client disconnects or cancels the HTTP request (possible in HTTP/2). Passing an HTTP request's context to QueryWithTimeout above would cause the database query to stop early either if the overall HTTP request was canceled or if the query took more than five seconds.
In some cases you can see “proxy error: context canceled” error message in the Gateway logs. The error itself means that the connection was closed unexpectedly. It can happen for various reasons, and in some cases it is totally fine: for example client can have unstable mobile internet.
The converse is false however: a canceled child context does not cancel its parent. Additionally, attaching values results in a new child context for each new key-value pair without mutating the parent.
Background returns a non-nil, empty Context. It is never canceled, has no values, and has no deadline. It is typically used by the main function, initialization, and tests, and as the top-level Context for incoming requests.
If you fail to cancel the context, the goroutine that WithCancel or WithTimeout created will be retained in memory indefinitely (until the program shuts down), causing a memory leak. If you do this a lot, your memory will balloon significantly. It's best practice to use a defer cancel()
immediately after calling WithCancel()
or WithTimeout()
If you use WithCancel
, the goroutine will be held indefinitely in memory. However, if you use WithDeadline
or WithTimeout
without calling cancel, the goroutine will only be held until the timer expires.
This is still not best practice though, it's always best to call cancel as soon as you're done with the resource.
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