The promise
package provides interfaces and utilities for writing asynchronous code in Go.
Promises and futures are constructs used for asynchronous and concurrent programming, allowing developers to work with values that may not be immediately available and can be evaluated in a different execution context.
Go is known for its built-in concurrency features like goroutines and channels. The select statement further allows for efficient multiplexing and synchronization of multiple channels, thereby enabling developers to coordinate and orchestrate asynchronous operations effectively. Additionally, the context package offers a standardized way to manage cancellation, deadlines, and timeouts within concurrent and asynchronous code.
On the other hand, Go's error handling mechanism, based on explicit error values returned from functions, provides a clear and concise way to handle errors.
The purpose of this package is to provide a library which simplifies the integration of concurrent code while providing a cohesive strategy for handling asynchronous errors. By adhering to Go's standard conventions for asynchronous and concurrent code, as well as error propagation, this package aims to enhance developer productivity and code reliability in scenarios requiring asynchronous operations.
Assuming you have a synchronous function func getMyIP(ctx context.Context) (string, error)
returning your external IP
address (see GetMyIP for an example).
Now you can do
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
defer cancel()
query := func() (string, error) {
return getMyIP(ctx)
}
future := promise.NewAsync(query)
and elsewhere in your program, even in a different goroutine
if ip, err := future.Await(ctx); err == nil {
slog.Info("Found IP", "ip", ip)
} else {
slog.Error("Failed to fetch IP", "error", err)
}
decoupling query construction from result processing.
Sample code to retrieve your IP address:
const serverURL = "https://httpbin.org/ip"
func getMyIP(ctx context.Context) (string, error) {
req, err := http.NewRequestWithContext(ctx, http.MethodGet, serverURL, nil)
if err != nil {
return "", err
}
req.Header.Set("Accept", "application/json")
resp, err := http.DefaultClient.Do(req)
if err != nil {
return "", err
}
defer func() { _ = resp.Body.Close() }()
ipResponse := struct {
Origin string `json:"origin"`
}{}
err = json.NewDecoder(resp.Body).Decode(&ipResponse)
return ipResponse.Origin, err
}
- Futures and Promises in the English Wikipedia