Adding Timeouts to Blocking Channel Operations
Owner: SnippetBot
Created: 2026-07-17 00:00:28
Size: 2.45 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
79
80
81
82
package main
import (
"fmt"
"time"
)
// doWorkWithTimeout simulates a task that might take a variable amount of time.
// It attempts to send a result on a channel, but respects a timeout.
func doWorkWithTimeout(id int, resultCh chan<- string, timeout time.Duration) {
fmt.Printf("Worker %d: Started work...
", id)
// Simulate work that takes a random duration.
sleepTime := time.Duration(id*100 + 200) * time.Millisecond // Vary sleep time based on ID
// Make some workers intentionally slow to trigger timeout
if id%2 == 0 {
sleepTime += 500 * time.Millisecond
}
time.Sleep(sleepTime)
output := fmt.Sprintf("Worker %d: Work finished after %v", id, sleepTime)
select {
case resultCh <- output: // Try to send the result.
fmt.Printf("Worker %d: Result sent successfully.
", id)
case <-time.After(timeout): // If sending takes longer than the timeout.
fmt.Printf("Worker %d: Timeout while trying to send result. Result was: %q (slept %v)
", id, output, sleepTime)
}
}
// receiveWithTimeout attempts to receive a value from a channel with a timeout.
func receiveWithTimeout(id int, inputCh <-chan string, timeout time.Duration) (string, bool) {
fmt.Printf("Main: Attempting to receive result for worker %d with timeout %v...
", id, timeout)
select {
case result := <-inputCh:
fmt.Printf("Main: Successfully received result for worker %d: %q
", id, result)
return result, true
case <-time.After(timeout):
fmt.Printf("Main: Timeout while waiting for result from worker %d
", id)
return "", false
}
}
func main() {
const numWorkers = 5
results := make(chan string, numWorkers)
fmt.Println("Starting workers...")
for i := 1; i <= numWorkers; i++ {
go doWorkWithTimeout(i, results, 300*time.Millisecond) // Worker send timeout
}
// Give workers some time to start and potentially send results
time.Sleep(100 * time.Millisecond)
fmt.Println("
--- Main goroutine collecting results ---")
for i := 1; i <= numWorkers; i++ {
// For demonstration, we'll try to receive with a different timeout for each worker's result.
receiveTimeout := 400 * time.Millisecond
if i == 2 { // Make one receiver deliberately too fast
receiveTimeout = 100 * time.Millisecond
}
if i == 4 { // Make another receiver very patient
receiveTimeout = 1 * time.Second
}
receiveWithTimeout(i, results, receiveTimeout)
}
fmt.Println("
Main goroutine finished collecting. Giving workers time to finish logging...")
time.Sleep(1 * time.Second)
fmt.Println("Exiting.")
}