When should I use client.CloseIdleConnections()?

In my function I make a get call using my simple client:
client := &http.Client{Timeout: time.Second * 10}

Then I do a Get request and return the response data. I do close the resonse body first:
response.Body.Close()

Do I still nbeed to call client.CloseIddleConnections ? It is not clear to me when to do that ? Can a GET connection done by me remain in status iddle after I received the response ? Also, exiting the function, is not the garbage collector supposed to clear any memory used by the clinet, and thus any iddle connections ?

Here’s the issue where CloseIdleConnections was first requested. Based on the example scenario in that issue, it sounds to me like you’re doing a similar thing: If you create a client in a function for one or a few requests, then before you return you should call CloseIdleConnections.

Potentially. http.Client caches its connections so that subsequent requests made to the same server(s) might not need to wait to establish a new connection.

Garbage collection will eventually clean up the memory and idle connections, but it’s not deterministic. If you have one or more functions called frequently that all create temporary http.Clients, they could all leave connections open and consume too much memory or too many file descriptors and won’t be able to open any more files or connections.

CloseIdleConnections should resolve that scenario, but I’d recommend keeping the same http.Client around so that you don’t need to make a new one every time.

Instead of this:

func GetSiteData() []byte {
	client := &http.Client{Timeout: time.Second * 10}
	defer client.CloseIdleConnections()
	resp, err := client.Get("http://example.com/")
	if err != nil {
		// handle error
	}
	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		// handle error
	}
	return body
}

You could just use the default HTTP client and specify the timeout in the request:

func GetSiteData() []byte {
	ctx, cancel := context.WithTimeout(context.TODO(), 10 * time.Second)
	defer cancel()
	req, err := http.NewRequestWithContext(ctx, http.MethodGet, "http://example.com/", nil)
	if err != nil {
		// handle error
	}
	resp, err := http.DefaultClient.Do(req)
	if err != nil {
		// handle error
	}
	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		// handle error
	}
	return body
}

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.