Skip to content

asmsh/promise

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

78 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Promise

PkgGoDev Go Report Card Tests

Fast, lightweight, and type-safe promises for Go... the Go way

Features

  • Type-Safe: Leverages Go generics for compile-time type safety.
  • Performance-First: Lock-free implementation optimized for high-throughput asynchronous workflows.
  • Go-Centric API: Focuses on Go idioms (multi-return parameters, error values, panic handling).
  • Automatic Panic Recovery: Built-in mechanisms to catch and handle goroutine panics safely.
  • Comprehensive Toolset: Support for chaining, grouping, delayed execution, and context integration.

Installation

go get github.com/asmsh/promise

Prerequisites

  • Go 1.23+

Usage

Starting a Promise

Simple goroutine (no return value):

p := promise.Go(func() {
    fmt.Println("Working...")
})
p.Wait()

Goroutine with a typed return value:

p := promise.GoFunc[string, any](func() (string, error) {
    return "Hello, Gopher!", nil
})

res := p.WaitRes()
fmt.Println(res.Val(), res.Err())

Chaining

Promises can be chained to build sequential asynchronous pipelines using Follow (returns a new Promise) and Callback (fire-and-forget):

promise.GoFunc[int, any](func() (int, error) {
    return 10, nil
}).Follow(func(ctx context.Context, res promise.Result[int]) promise.Result[int] {
    if res.State() != promise.Success {
        fmt.Println("Error:", res.Err())
        return res
    }
    return promise.ValRes(res.Val() * 2)
}).Callback(func(ctx context.Context, res promise.Result[int]) {
    fmt.Println("Done, final state:", res.State())
})

Grouping

A Group manages multiple related promises sharing a goroutine pool:

g := promise.NewGroup[string]()

g.GoValErr(func() (string, error) { return "task 1", nil })
g.GoValErr(func() (string, error) { return "task 2", nil })

// Block until all finish and collect every result
allRes := g.AllWaitRes()
for _, r := range allRes.Val() {
    fmt.Println(r.Val())
}

Combining Independent Promises

Several functions combine multiple unrelated promises:

p1 := promise.GoFunc[string, any](func() (string, error) { return "one", nil })
p2 := promise.GoFunc[string, any](func() (string, error) { return "two", nil })
p3 := promise.GoFunc[string, any](func() (string, error) { return "three", nil })

// Wait for all and collect every result
joined := promise.Join(p1, p2, p3)
for _, r := range joined.WaitRes().Val() {
    fmt.Println(r.Val())
}

Other combinators: All (short-circuits on failure), AllWait, Any (short-circuits on first success), AnyWait, Select (first to resolve).

Comparisons

Feature promise sync.WaitGroup Raw Channels
Return Values ✅ Yes (Typed) ❌ No ✅ Yes (Manual)
Error Handling ✅ First-class ❌ No ✅ Manual
Chaining ✅ Built-in ❌ No ❌ No
Panic Safety ✅ Automatic ❌ No ❌ No
Complexity Low Low Medium/High

About

Fast, lightweight, and type-safe promises for Go... the Go way. Providing an efficient and idiomatic way for managing and creating asynchronous pipelines in Go.

Topics

Resources

License

Stars

Watchers

Forks

Contributors

Languages