Search and navigate

Pages

Start HereRoadmapTutorialsCheatsheetInterview QuestionsResources

Published tutorials

Building a REST API with Go: The Complete TutorialGeneric Functions in Go: Writing Reusable CodeGo Benchmarking: Measuring Performance with testing.BGo Channels: Communication Between GoroutinesGo Constraints: comparable, Ordered and Custom SetsGo Context: Cancellation, Deadlines, and Request ValuesGo HTTP Client: Timeouts, JSON, and Reliable RequestsGo HTTP Middleware: Build a Production ChainGo Interview Questions: 25 Answers That Show UnderstandingGo Mutex: Protecting Shared State from Race ConditionsGo net/http: Build an HTTP Server from ScratchGo select Statement: Multiplexing Channels ExplainedGo Tools You Need for a Reliable Development LoopGo Tutorial: From First Program to Backend FoundationsGo Type Parameters: Syntax and Constraints ExplainedGo Worker Pool Pattern: Bounded Concurrency at ScaleGo's Type System Deep Dive: Static Typing Done RightGolang Compilation and Execution ExplainedGolang File Structure for Modules and ApplicationsGolang Hello World and Your First Go ProgramGolang IDEs: Choose an Editor for Your WorkflowGolang Interfaces: What They Are and How to Use ThemGoroutine Leaks in Go: How to Detect and Prevent ThemGoroutines in Go: Concurrency Without LeaksHow to Download and Install Golang SafelyHow to Learn Golang with a Focused Study PlanIntegration Testing in Go: Testing Real BoundariesJSON in Go: Encoding, Decoding, and ValidationLearn Golang with a Practical Beginner CourseMocking in Go: Test Doubles Without Magicsync.WaitGroup in Go: Coordinating Multiple GoroutinesTable-Driven Tests in Go: The Idiomatic WayTesting in Go: Table Tests, HTTP, Fakes, and CoverageWhat Is Go and How Does a Go Program Work?Why Learn Golang and What Is Go Used For?Writing Unit Tests in Go: A Practical Guide
Open full search and filters →

Go HTTP Client: Timeouts, JSON, and Reliable Requests

Build reliable outbound HTTP requests in Go with client timeouts, context, JSON, status checks, body limits, and transport reuse.

Standard-library lessonGo requirement: Go 1.21+How tutorials are checked
Web & APIs · Lesson 3Saved in this browser. No account required.

Verification (10 August 2026): Self-contained runnable examples were compile-tested with Go 1.26.5 on Windows/amd64. Multi-file or contextual snippets and intentional compiler-error demonstrations were checked separately in the repository verification matrix.

Go’s http.Client is safe for concurrent use and should usually be reused. A zero-value client has no overall timeout, so production code should configure one or rely on request deadlines deliberately.

Create and send a request

client := &http.Client{Timeout: 5 * time.Second}

req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)
if err != nil {
	return err
}
req.Header.Set("Accept", "application/json")

res, err := client.Do(req)
if err != nil {
	return err
}
defer res.Body.Close()

Closing the body permits connection reuse. For small responses, read it fully; for large or untrusted responses, impose a limit.

Check status before decoding

if res.StatusCode < 200 || res.StatusCode >= 300 {
	body, _ := io.ReadAll(io.LimitReader(res.Body, 8<<10))
	return fmt.Errorf("upstream status %d: %s", res.StatusCode, body)
}

Do not decode an error response into the success type. Limit captured error bodies so an upstream cannot force large allocations or logs.

Send JSON

payload, err := json.Marshal(input)
if err != nil { return err }

req, err := http.NewRequestWithContext(ctx, http.MethodPost, url, bytes.NewReader(payload))
req.Header.Set("Content-Type", "application/json")

Configure transport carefully

The default transport already pools connections. Clone it before customization rather than constructing an incomplete transport from scratch. Configure dial, TLS, response-header, and idle-connection timeouts based on the service’s latency budget.

Retries are safe only when the operation is idempotent or uses an idempotency key. Retry a narrow set of transient failures with backoff and a total deadline; never create an infinite retry loop.