mirror of
https://github.com/foomo/gofuncy.git
synced 2026-07-05 00:40:09 +00:00
335 lines
5.4 KiB
Markdown
335 lines
5.4 KiB
Markdown
---
|
|
prev:
|
|
text: Channel
|
|
link: /api/channel
|
|
|
|
next:
|
|
text: Advanced Examples
|
|
link: /examples/advanced
|
|
---
|
|
|
|
# Basic Examples
|
|
|
|
## Fire-and-Forget
|
|
|
|
Spawn a background goroutine. Errors are logged automatically.
|
|
|
|
```go
|
|
package main
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"time"
|
|
|
|
"github.com/foomo/gofuncy"
|
|
)
|
|
|
|
func main() {
|
|
ctx := context.Background()
|
|
|
|
gofuncy.Go(ctx, func(ctx context.Context) error {
|
|
fmt.Println("running in the background")
|
|
return nil
|
|
})
|
|
|
|
time.Sleep(100 * time.Millisecond)
|
|
}
|
|
```
|
|
|
|
## Custom Error Handler
|
|
|
|
Override the default slog handler to handle errors yourself.
|
|
|
|
```go
|
|
package main
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"fmt"
|
|
"time"
|
|
|
|
"github.com/foomo/gofuncy"
|
|
)
|
|
|
|
func main() {
|
|
ctx := context.Background()
|
|
|
|
gofuncy.Go(ctx, func(ctx context.Context) error {
|
|
return errors.New("something went wrong")
|
|
},
|
|
gofuncy.WithName("custom-handler"),
|
|
gofuncy.WithErrorHandler(func(ctx context.Context, err error) {
|
|
fmt.Printf("[%s] error: %v\n", gofuncy.NameFromContext(ctx), err)
|
|
}),
|
|
)
|
|
|
|
time.Sleep(100 * time.Millisecond)
|
|
// Output: [custom-handler] error: something went wrong
|
|
}
|
|
```
|
|
|
|
## Async with Deferred Result
|
|
|
|
Launch work now, collect the result when you need it. The wait function is safe to call from multiple goroutines.
|
|
|
|
```go
|
|
package main
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
|
|
"github.com/foomo/gofuncy"
|
|
)
|
|
|
|
func main() {
|
|
ctx := context.Background()
|
|
|
|
var user string
|
|
var orders []string
|
|
|
|
// Launch two async calls
|
|
waitUser := gofuncy.Wait(ctx, func(ctx context.Context) error {
|
|
user = "Alice"
|
|
return nil
|
|
})
|
|
|
|
waitOrders := gofuncy.Wait(ctx, func(ctx context.Context) error {
|
|
orders = []string{"order-1", "order-2"}
|
|
return nil
|
|
})
|
|
|
|
// Wait for both
|
|
if err := waitUser(); err != nil {
|
|
fmt.Println("user error:", err)
|
|
return
|
|
}
|
|
if err := waitOrders(); err != nil {
|
|
fmt.Println("orders error:", err)
|
|
return
|
|
}
|
|
|
|
fmt.Printf("%s has %d orders\n", user, len(orders))
|
|
// Output: Alice has 2 orders
|
|
}
|
|
```
|
|
|
|
## Synchronous Execution with Do
|
|
|
|
Run a function through the full middleware chain without spawning a goroutine. Useful for inline calls that need retry, timeout, or circuit breaker.
|
|
|
|
```go
|
|
package main
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"time"
|
|
|
|
"github.com/foomo/gofuncy"
|
|
)
|
|
|
|
func main() {
|
|
ctx := context.Background()
|
|
|
|
err := gofuncy.Do(ctx, func(ctx context.Context) error {
|
|
// Simulate a flaky call
|
|
return fmt.Errorf("connection refused")
|
|
},
|
|
gofuncy.WithRetry(3, gofuncy.RetryBackoff(gofuncy.BackoffConstant(100*time.Millisecond))),
|
|
gofuncy.WithTimeout(500*time.Millisecond),
|
|
)
|
|
if err != nil {
|
|
fmt.Println("failed after retries:", err)
|
|
}
|
|
}
|
|
```
|
|
|
|
## Basic Group
|
|
|
|
Run multiple functions concurrently and collect all errors.
|
|
|
|
```go
|
|
package main
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"fmt"
|
|
|
|
"github.com/foomo/gofuncy"
|
|
)
|
|
|
|
func main() {
|
|
ctx := context.Background()
|
|
|
|
g := gofuncy.NewGroup(ctx)
|
|
|
|
g.Add(func(ctx context.Context) error {
|
|
fmt.Println("task A")
|
|
return nil
|
|
})
|
|
|
|
g.Add(func(ctx context.Context) error {
|
|
fmt.Println("task B")
|
|
return errors.New("task B failed")
|
|
})
|
|
|
|
g.Add(func(ctx context.Context) error {
|
|
fmt.Println("task C")
|
|
return nil
|
|
})
|
|
|
|
if err := g.Wait(); err != nil {
|
|
fmt.Println("group error:", err)
|
|
}
|
|
// Output (order may vary):
|
|
// task A
|
|
// task B
|
|
// task C
|
|
// group error: task B failed
|
|
}
|
|
```
|
|
|
|
## All Over a Slice
|
|
|
|
Iterate over items concurrently with a concurrency limit.
|
|
|
|
```go
|
|
package main
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"time"
|
|
|
|
"github.com/foomo/gofuncy"
|
|
)
|
|
|
|
func main() {
|
|
ctx := context.Background()
|
|
|
|
items := []string{"alpha", "bravo", "charlie", "delta", "echo"}
|
|
|
|
err := gofuncy.All(ctx, items, func(ctx context.Context, item string) error {
|
|
fmt.Printf("processing %s\n", item)
|
|
time.Sleep(50 * time.Millisecond) // simulate work
|
|
return nil
|
|
},
|
|
gofuncy.WithLimit(2), // process 2 at a time
|
|
)
|
|
if err != nil {
|
|
fmt.Println("errors:", err)
|
|
}
|
|
}
|
|
```
|
|
|
|
## Channel
|
|
|
|
Send and receive values through an observable channel with built-in metrics.
|
|
|
|
```go
|
|
package main
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
|
|
"github.com/foomo/gofuncy/channel"
|
|
)
|
|
|
|
func main() {
|
|
ctx := context.Background()
|
|
|
|
ch := channel.New[int](channel.WithBuffer[int](5))
|
|
|
|
// Send multiple values at once
|
|
if err := ch.Send(ctx, 1, 2, 3, 4, 5); err != nil {
|
|
fmt.Println("send error:", err)
|
|
return
|
|
}
|
|
|
|
fmt.Printf("buffered: %d/%d\n", ch.Len(), ch.Cap())
|
|
// Output: buffered: 5/5
|
|
|
|
// Close and drain
|
|
ch.Close()
|
|
|
|
for v := range ch.Receive() {
|
|
fmt.Println(v)
|
|
}
|
|
}
|
|
```
|
|
|
|
## Map with Result Collection
|
|
|
|
Transform items concurrently and collect results in order.
|
|
|
|
```go
|
|
package main
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
|
|
"github.com/foomo/gofuncy"
|
|
)
|
|
|
|
func main() {
|
|
ctx := context.Background()
|
|
|
|
numbers := []int{1, 2, 3, 4, 5}
|
|
|
|
squares, err := gofuncy.Map(ctx, numbers, func(ctx context.Context, n int) (int, error) {
|
|
return n * n, nil
|
|
})
|
|
if err != nil {
|
|
fmt.Println("error:", err)
|
|
return
|
|
}
|
|
|
|
fmt.Println(squares) // [1 4 9 16 25]
|
|
}
|
|
```
|
|
|
|
## Stoppable Goroutine with GoWithCancel
|
|
|
|
Spawn a goroutine and stop it later.
|
|
|
|
```go
|
|
package main
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"time"
|
|
|
|
"github.com/foomo/gofuncy"
|
|
)
|
|
|
|
func main() {
|
|
stop := gofuncy.GoWithCancel(context.Background(), func(ctx context.Context) error {
|
|
for {
|
|
select {
|
|
case <-ctx.Done():
|
|
fmt.Println("stopped")
|
|
return nil
|
|
case <-time.After(100 * time.Millisecond):
|
|
fmt.Println("tick")
|
|
}
|
|
}
|
|
})
|
|
|
|
time.Sleep(350 * time.Millisecond)
|
|
stop()
|
|
time.Sleep(50 * time.Millisecond)
|
|
// Output:
|
|
// tick
|
|
// tick
|
|
// tick
|
|
// stopped
|
|
}
|
|
```
|