This documentation is still new and evolving. If you spot any mistakes, unclear explanations, or missing details, please open an issue.
Your feedback helps us improve!
Core - Concurrency helpersโ
This page lists all concurrency operations available in the core package of lo.
NewDebounceโ
Creates a debounced function that delays invoking the callbacks until after the wait duration has elapsed since the last call. Returns the debounced function and a cancel function.
debounce, cancel := lo.NewDebounce(
100 * time.Millisecond,
func() {
println("Called once after debounce!")
},
)
for i := 0; i < 10; i++ {
debounce()
}
time.Sleep(200 * time.Millisecond)
cancel()Prototype:func NewDebounce(duration time.Duration, f ...func()) (func(), func())
Synchronizeโ
Wraps a callback in a mutex to ensure sequential execution. Optionally accepts a custom locker.
s := lo.Synchronize()
for i := 0; i < 10; i++ {
go s.Do(func() { println("sequential") })
}Similar:Prototype:func Synchronize(opt ...sync.Locker) *synchronize
AsyncXโ
Runs a function asynchronously and returns results via channels. Variants support 0 to 6 return values, using tuple types for multi-value results.
Variants:
Async
,Async0..Async6
ch := lo.Async(func() int {
time.Sleep(10 * time.Millisecond)
return 42
})
v := <-ch
done := lo.Async0(func() {
time.Sleep(5 * time.Millisecond)
})
<-doneVariant:Prototypes:func Async[A any](f func() A) <-chan A
func Async0(f func()) <-chan struct{}
func Async1[A any](f func() A) <-chan A
func Async2[A, B any](f func() (A, B)) <-chan Tuple2[A, B]
func Async3[A, B, C any](f func() (A, B, C)) <-chan Tuple3[A, B, C]
func Async4[A, B, C, D any](f func() (A, B, C, D)) <-chan Tuple4[A, B, C, D]
func Async5[A, B, C, D, E any](f func() (A, B, C, D, E)) <-chan Tuple5[A, B, C, D, E]
func Async6[A, B, C, D, E, F any](f func() (A, B, C, D, E, F)) <-chan Tuple6[A, B, C, D, E, F]NewDebounceByโ
Creates a debounced function per key that delays invoking callbacks until after the wait duration has elapsed for that key. Returns a per-key debounced function and a per-key cancel function.
debounce, cancel := lo.NewDebounceBy[string](
100*time.Millisecond,
func(key string, count int) {
println(key, count)
},
)
for i := 0; i < 10; i++ {
debounce("first")
}
time.Sleep(200 * time.Millisecond)
cancel("first")Prototype:func NewDebounceBy[T comparable](duration time.Duration, f ...func(key T, count int)) (func(key T), func(key T))
WaitForโ
Runs periodically until a condition is validated. Use WaitFor for simple predicates, or WaitForWithContext when you need context cancellation/timeout inside the predicate. Both return total iterations, elapsed time, and whether the condition became true.
iterations, elapsed, ok := lo.WaitFor(
func(i int) bool {
return i > 5
},
10*time.Millisecond,
time.Millisecond,
)With context:
iterations, elapsed, ok := lo.WaitForWithContext(
context.Background(),
func(_ context.Context, i int) bool {
return i >= 5
},
10*time.Millisecond,
time.Millisecond,
)Variant:Prototypes:func WaitFor(condition func(i int) bool, timeout time.Duration, heartbeatDelay time.Duration) (totalIterations int, elapsed time.Duration, conditionFound bool)
func WaitForWithContext(ctx context.Context, condition func(ctx context.Context, i int) bool, timeout time.Duration, heartbeatDelay time.Duration) (totalIterations int, elapsed time.Duration, conditionFound bool)NewTransactionโ
Creates a new Saga transaction that chains steps with rollback functions.
Use Then to add steps with exec and rollback functions. Call Process with an initial state to execute the pipeline; if a step returns an error, previously executed steps are rolled back in reverse order using their rollback functions.
type Acc struct{ Sum int }
tx := lo.NewTransaction[Acc]().
Then(
func(a Acc) (Acc, error) {
a.Sum += 10
return a, nil
},
func(a Acc) Acc {
a.Sum -= 10
return a
},
).
Then(
func(a Acc) (Acc, error) {
a.Sum *= 3
return a, nil
},
func(a Acc) Acc {
a.Sum /= 3
return a
},
)
res, err := tx.Process(Acc{Sum: 1})
// res.Sum == 33, err == nilSimilar:Prototype:func NewTransaction[T any]() *Transaction[T]
NewThrottleโ
Creates a throttled function that invokes callbacks at most once per interval. Returns the throttled function and a reset function.
throttle, reset := lo.NewThrottle(
100*time.Millisecond,
func() {
println("tick")
},
)
for i := 0; i < 10; i++ {
throttle();
time.Sleep(30*time.Millisecond)
}
reset()Prototype:func NewThrottle(interval time.Duration, f ...func()) (throttle func(), reset func())
NewThrottleWithCountโ
Creates a throttled function with a per-interval invocation limit.
throttle, reset := lo.NewThrottleWithCount(
100*time.Millisecond,
3,
func() {
println("tick")
},
)
for i := 0; i < 10; i++ {
throttle();
time.Sleep(30*time.Millisecond)
}
reset()Prototype:func NewThrottleWithCount(interval time.Duration, count int, f ...func()) (throttle func(), reset func())
NewThrottleByโ
Creates a throttled function per key.
throttle, reset := lo.NewThrottleBy[string](
100*time.Millisecond,
func(key string) {
println(key)
},
)
for i := 0; i < 10; i++ {
throttle("foo");
time.Sleep(30*time.Millisecond)
}
reset()Prototype:func NewThrottleBy[T comparable](interval time.Duration, f ...func(key T)) (throttle func(key T), reset func())
NewThrottleByWithCountโ
Creates a throttled function per key with a per-interval invocation limit.
throttle, reset := lo.NewThrottleByWithCount[string](
100*time.Millisecond,
3,
func(key string) {
println(key)
},
)
for i := 0; i < 10; i++ {
throttle("foo")
}
reset()Prototype:func NewThrottleByWithCount[T comparable](interval time.Duration, count int, f ...func(key T)) (throttle func(key T), reset func())