Go Channel-based Future/Promise Pattern for Asynchronous Results
Owner: SnippetBot
Created: 2026-07-25 00:00:52
Size: 2.15 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
83
84
85
package main
import (
"fmt"
"time"
)
// FutureResult holds either a value or an error.
type FutureResult struct {
Value interface{}
Err error
}
// AsyncOperation simulates a long-running task and returns a channel
// that will eventually provide the result.
func AsyncOperation(taskID int, delay time.Duration, shouldFail bool) <-chan FutureResult {
resultCh := make(chan FutureResult, 1) // Buffered channel for single result
go func() {
fmt.Printf("Task %d: Starting asynchronous work...
", taskID)
time.Sleep(delay)
if shouldFail {
resultCh <- FutureResult{Err: fmt.Errorf("task %d failed after %v", taskID, delay)}
} else {
resultCh <- FutureResult{Value: fmt.Sprintf("Data from task %d (completed in %v)", taskID, delay)}
}
close(resultCh) // Important: close the channel when done sending
}()
return resultCh
}
func main() {
fmt.Println("Main: Kicking off asynchronous operations.")
// Start several async operations
future1 := AsyncOperation(1, 2*time.Second, false)
future2 := AsyncOperation(2, 1*time.Second, true)
future3 := AsyncOperation(3, 3*time.Second, false)
// In a real web server, you might continue handling other requests here
// while these operations run in the background.
fmt.Println("Main: Continuing with other work while tasks run...")
time.Sleep(500 * time.Millisecond)
fmt.Println("Main: Some other work done, now waiting for results.")
// Wait for and process results using a select statement
for i := 0; i < 3; i++ {
select {
case res := <-future1:
if res.Err != nil {
fmt.Printf("Future 1 Error: %v
", res.Err)
} else {
fmt.Printf("Future 1 Success: %v
", res.Value)
}
future1 = nil // Mark as processed to avoid re-selecting
case res := <-future2:
if res.Err != nil {
fmt.Printf("Future 2 Error: %v
", res.Err)
} else {
fmt.Printf("Future 2 Success: %v
", res.Value)
}
future2 = nil // Mark as processed
case res := <-future3:
if res.Err != nil {
fmt.Printf("Future 3 Error: %v
", res.Err)
} else {
fmt.Printf("Future 3 Success: %v
", res.Value)
}
future3 = nil // Mark as processed
}
}
fmt.Println("Main: All asynchronous results processed.")
}