Timeout for External API Calls with Go Channels and Context
Owner: SnippetBot
Created: 2026-10-01 00:00:44
Size: 1.95 KB
Expires: Never
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
package main
import (
"context"
"fmt"
"log"
"net/http"
"time"
)
// simulateExternalAPICall simulates a call to an external API
func simulateExternalAPICall(ctx context.Context) (string, error) {
// Simulate varying response times
delay := 3 * time.Second
// For demonstration, let's make some calls intentionally slow
if ctx.Value("callID").(int)%2 == 0 {
delay = 6 * time.Second // Every other call is slow
}
select {
case <-time.After(delay):
return fmt.Sprintf("Data from external API (delay %v)", delay), nil
case <-ctx.Done():
return "", ctx.Err() // Context was canceled or timed out
}
}
func main() {
fmt.Println("Starting external API call timeout example...")
for i := 1; i <= 5; i++ {
// Create a context with a timeout for each call
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
ctx = context.WithValue(ctx, "callID", i) // Add a call ID for logging
defer cancel() // Ensure resources are cleaned up
fmt.Printf("
Attempting API call %d with 5s timeout...
", i)
result, err := simulateExternalAPICall(ctx)
if err != nil {
if err == context.DeadlineExceeded {
fmt.Printf("API Call %d timed out: %v
", i, err)
} else {
fmt.Printf("API Call %d failed: %v
", i, err)
}
} else {
fmt.Printf("API Call %d succeeded: %s
", i, result)
}
}
// Example with an HTTP request client timeout
fmt.Println("
--- HTTP Client Timeout Example ---")
client := &http.Client{
Timeout: 2 * time.Second, // Global timeout for client requests
}
req, err := http.NewRequest("GET", "https://httpbin.org/delay/3", nil) // This will intentionally delay for 3s
if err != nil {
log.Fatal(err)
}
fmt.Println("Making HTTP GET request to httpbin.org/delay/3 with client timeout 2s...")
resp, err := client.Do(req)
if err != nil {
fmt.Printf("HTTP Request failed: %v
", err)
} else {
defer resp.Body.Close()
fmt.Printf("HTTP Request succeeded (Status: %s)
", resp.Status)
}
}