package main import ( "fmt" "time" ) // Future represents a value that will be available in the future. type Future[T any] struct { result chan T error chan error } // Get blocks until the result or an error is available. func (f *Future[T]) Get() (T, error) { select { case res := <-f.result: return res, nil case err := <-f.error: var zero T return zero, err } } // Async executes a function asynchronously and returns a Future. func Async[T any](fn func() (T, error)) *Future[T] { f := &Future[T]{ result: make(chan T, 1), error: make(chan error, 1), } go func() { res, err := fn() if err != nil { f.error <- err } else { f.result <- res } // Close channels to signal completion and prevent further writes close(f.result) close(f.error) }() return f } // simulateNetworkRequest simulates an async operation that might succeed or fail. func simulateNetworkRequest(success bool) (string, error) { fmt.Println("Simulating network request...") time.Sleep(2 * time.Second) if success { return "Data received from API!", nil } else { return "", fmt.Errorf("network error: failed to fetch data") } } func main() { // Example 1: Successful async operation fmt.Println("Starting successful async operation...") future1 := Async(func() (string, error) { return simulateNetworkRequest(true) }) // Do other work while waiting... fmt.Println("Main routine is doing other work...") time.Sleep(1 * time.Second) res1, err1 := future1.Get() if err1 != nil { fmt.Printf("Error (Future 1): %v ", err1) } else { fmt.Printf("Result (Future 1): %s ", res1) } fmt.Println(" ---------------------------------- ") // Example 2: Failed async operation fmt.Println("Starting failed async operation...") future2 := Async(func() (string, error) { return simulateNetworkRequest(false) }) fmt.Println("Main routine is doing other work again...") time.Sleep(1 * time.Second) res2, err2 := future2.Get() if err2 != nil { fmt.Printf("Error (Future 2): %v ", err2) } else { fmt.Printf("Result (Future 2): %s ", res2) } fmt.Println("Main routine finished.") }