Basic HTTP Client
The default http.Client is rarely suitable for production. It has no timeouts, no retries, and limited connection pooling. Always configure a custom client.
http.Get and http.Post are shortcuts. http.NewRequest creates a custom request. Always close resp.Body to prevent connection leaks. Set headers on the request, not the client.
Timeout Configuration
Gotimeout-configuration.go
Client.Timeout sets the total request timeout. Transport timeouts control individual phases: connection, TLS handshake, response headers, and idle connections. Context timeout provides per-request control.
Transport Tuning
Gotransport-configuration.go
MaxIdleConnsPerHost controls per-host connection pooling. Increase it for services that make many requests to the same host. MaxConnsPerHost limits total connections per host. Always reuse clients — they are designed for concurrent use.
Retry Patterns
Exponential backoff increases wait time between retries. Jitter prevents thundering herd. Retry on 5xx errors and network errors. Do not retry on 4xx errors (client errors). Always respect context cancellation.
Request Tracing
Gohttp-request-tracing.go
httptrace captures timing for each phase of the request. DNSStart/Done measure DNS resolution. ConnectStart/Done measure TCP connection. GotFirstResponseByte measures server processing time. Use this to diagnose slow requests.
Production Client
Goproduction-http-client.go
A production client wraps http.Client with logging, error handling, and structured configuration. Reuse the client across requests. Log request duration and status codes. Handle errors with context. This is the standard pattern for API clients.
Not closing resp.Body leaks connections. Even on error, close the body. Use defer resp.Body.Close() immediately after checking the error. This is the most common HTTP client bug in Go.