Context Leak in Go: Implications of Skipping defer cancel()
In Go, the context package provides a way to pass cancellation to concurrent routines. The context.WithTimeout function creates a new context with a timeout that will be canceled after the specified duration. If the resulting cancel function is not called, a context leak will occur.
In the provided code snippet:
func Call(ctx context.Context, payload Payload) (Response, error) { req, err := http.NewRequest(...) ctx, cancel = context.WithTimeout(ctx, time.Duration(3) * time.Second) //defer cancel() missing here return http.DefaultClient.Do(req) }
Without the defer cancel() statement, the cancel function is not invoked and the goroutine created by WithTimeout continues to exist indefinitely. This is a memory leak because the goroutine will remain in memory until the program exits, even if the request has been completed.
The go vet tool warns about this leak because it can lead to excessive memory consumption if the leak occurs frequently. Chronic memory leaks can eventually cause system performance issues or even crashes.
To avoid context leaks, it is crucial to call the cancel function when the context is no longer needed. The best practice is to use a defer cancel() statement immediately after calling WithCancel or WithTimeout, as shown in the following modified code:
func Call(ctx context.Context, payload Payload) (Response, error) { req, err := http.NewRequest(...) ctx, cancel = context.WithTimeout(ctx, time.Duration(3) * time.Second) defer cancel() // Added defer cancel() to release resources return http.DefaultClient.Do(req) }
By adhering to this practice, you ensure that the goroutine and associated resources are released promptly after use, minimizing the potential for memory leaks and optimizing system performance.
The above is the detailed content of Why is `defer cancel()` crucial to prevent context leaks in Go?. For more information, please follow other related articles on the PHP Chinese website!