๐Ÿ“กHTTP ClientLESSON

HTTP Client

Never use the default http.Get in production

http.Get(url) uses the default client which has no timeout. A slow server can hang your goroutine forever:

Always create a client with an explicit timeout:

Always close the response body

An unclosed response body holds a TCP connection in the pool. Always defer resp.Body.Close() immediately after checking the error.

Checking status codes

The HTTP client does not return an error for 4xx/5xx responses โ€” only network errors:

Check resp.StatusCode explicitly after every request.

Building a request manually

client.Do(req) gives full control over method, headers, and body:

Always prefer http.NewRequestWithContext over http.NewRequest so the request respects context cancellation.

Reading JSON responses

json.NewDecoder reads directly from the response body without buffering the entire payload โ€” important for large responses.

Custom transport for connection pooling

Create the client once at startup (package-level or in a struct) and reuse it. Creating a new http.Client per request bypasses connection pooling.

Retries with exponential backoff

For transient failures (5xx, network errors), retry with backoff:

Knowledge Check

Why should you always create `http.Client{Timeout: ...}` rather than using `http.Get` directly?

What happens if you forget to call `resp.Body.Close()`?

Why use http.NewRequestWithContext instead of http.NewRequest?