go
46 lines · 6 steps
Fetching a charge over HTTP in Go
A timeout-bounded API client method that builds a request, checks the response, and decodes JSON into a typed struct.
Explained by
highlit
1package payments
2
3import (
4 "context"
5 "encoding/json"
6 "fmt"
7 "net/http"
8 "time"
9)
10
11type Charge struct {
12 ID string `json:"id"`
13 Status string `json:"status"`
14 Amount int64 `json:"amount"`
15}
16
17func (c *Client) FetchCharge(ctx context.Context, id string) (*Charge, error) {
18 ctx, cancel := context.WithTimeout(ctx, 3*time.Second)
19 defer cancel()
20
21 url := fmt.Sprintf("%s/v1/charges/%s", c.baseURL, id)
22 req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)
23 if err != nil {
24 return nil, fmt.Errorf("build request: %w", err)
25 }
26 req.Header.Set("Authorization", "Bearer "+c.apiKey)
27
28 resp, err := c.http.Do(req)
29 if err != nil {
30 if ctx.Err() == context.DeadlineExceeded {
31 return nil, fmt.Errorf("fetch charge %s: timed out", id)
32 }
33 return nil, fmt.Errorf("fetch charge %s: %w", id, err)
34 }
35 defer resp.Body.Close()
36
37 if resp.StatusCode != http.StatusOK {
38 return nil, fmt.Errorf("fetch charge %s: unexpected status %d", id, resp.StatusCode)
39 }
40
41 var charge Charge
42 if err := json.NewDecoder(resp.Body).Decode(&charge); err != nil {
43 return nil, fmt.Errorf("decode charge: %w", err)
44 }
45 return &charge, nil
46}
01 / 01
STEP 01
‹ swipe to step through ›
Walkthrough
Space play
←→ step
click any line
Three takeaways
- 1Deriving a timeout context and deferring cancel bounds the whole request lifecycle in one place.
- 2Wrapping errors with %w preserves the underlying cause while adding call-site context.
- 3Inspecting ctx.Err() lets you turn a generic transport failure into a clear timeout message.
Related explainers
java
@Service public class InventoryService { private final RestClient warehouseClient;
Bulkhead-protected HTTP calls in Spring
bulkhead
resilience
fallback
Intermediate
7 steps
go
func UploadDocument(c *gin.Context) { fileHeader, err := c.FormFile("file") if err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": "file is required"})
Handling multipart uploads in Gin
multipart-upload
validation
error-handling
Intermediate
9 steps
go
package handlers type WebhookEvent struct { ID string `json:"id"`
Verifying and processing webhooks in Gin
webhooks
hmac
idempotency
Intermediate
9 steps
go
package logparse import ( "bufio"
Splitting multi-line logs with a Scanner
parsing
streaming
bufio
Intermediate
9 steps
go
package handlers import ( "net/http"
Custom validators and binding in Gin
validation
struct-tags
error-handling
Intermediate
8 steps
go
package hashring import ( "hash/crc32"
How consistent hashing works in Go
consistent-hashing
load-balancing
concurrency
Intermediate
8 steps
Share this explainer
Here's the card — post it anywhere.
Made with highlit — turn any snippet into a walkthrough like this in about a minute.
Explain your code
Embed this explainer
Drop the interactive walkthrough into a blog or docs. Views never cost a credit.
<iframe src="https://highlit.co/explainers/fetching-a-charge-over-http-in-go-explained-go-87fd/embed?autoplay=1" width="100%" height="520" loading="lazy" style="border:0"></iframe>
Autoplay is on by default — add ?autoplay=0 to start paused.