From 13730306afce103b3ead59bb65ccfb0ab88039b8 Mon Sep 17 00:00:00 2001 From: CorentinClabaut Date: Tue, 26 Apr 2022 15:56:41 +0200 Subject: [PATCH] Add Async2-6 returning tuple inside the channel --- README.md | 17 +++++---- concurrency.go | 49 +++++++++++++++++++++++- concurrency_test.go | 90 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 146 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 32c9d227..ccc355e3 100644 --- a/README.md +++ b/README.md @@ -1246,18 +1246,13 @@ Executes a function in a goroutine and returns the result in a channel. ```go ch := lo.Async(func() error { time.Sleep(10 * time.Second); return nil }) // chan error (nil) - -ch := lo.Async(func() lo.Tuple2[int, error] { - time.Sleep(10 * time.Second); - return lo.Tuple2[int, error]{42, nil} -}) -// chan lo.Tuple2[int, error] ({42, nil}) ``` -### Async{0->1} +### Async{0->6} Executes a function in a goroutine and returns the result in a channel. -For function without return, the channel will be set once the function finishes. +For function with multiple return values, the results will be returned as a tuple inside the channel. +For function without return, struct{} will be returned in the channel. ```go ch := lo.Async0(func() { time.Sleep(10 * time.Second) }) @@ -1268,6 +1263,12 @@ ch := lo.Async1(func() int { return 42 }) // chan int (42) + +ch := lo.Async2(func() (int, string) { + time.Sleep(10 * time.Second); + return 42, "Hello" +}) +// chan lo.Tuple2[int, string] ({42, "Hello"}) ``` ### Must diff --git a/concurrency.go b/concurrency.go index 9c2afeda..2c112141 100644 --- a/concurrency.go +++ b/concurrency.go @@ -1,8 +1,8 @@ package lo // Async executes a function in a goroutine and returns the result in a channel. -func Async[T any](f func() T) chan T { - ch := make(chan T) +func Async[A any](f func() A) chan A { + ch := make(chan A) go func() { ch <- f() }() @@ -23,3 +23,48 @@ func Async0(f func()) chan struct{} { func Async1[A any](f func() A) chan A { return Async(f) } + +// Async2 has the same behavior as Async, but returns the 2 results as a tuple inside the channel. +func Async2[A any, B any](f func() (A, B)) chan Tuple2[A, B] { + ch := make(chan Tuple2[A, B]) + go func() { + ch <- T2(f()) + }() + return ch +} + +// Async3 has the same behavior as Async, but returns the 3 results as a tuple inside the channel. +func Async3[A any, B any, C any](f func() (A, B, C)) chan Tuple3[A, B, C] { + ch := make(chan Tuple3[A, B, C]) + go func() { + ch <- T3(f()) + }() + return ch +} + +// Async4 has the same behavior as Async, but returns the 4 results as a tuple inside the channel. +func Async4[A any, B any, C any, D any](f func() (A, B, C, D)) chan Tuple4[A, B, C, D] { + ch := make(chan Tuple4[A, B, C, D]) + go func() { + ch <- T4(f()) + }() + return ch +} + +// Async5 has the same behavior as Async, but returns the 5 results as a tuple inside the channel. +func Async5[A any, B any, C any, D any, E any](f func() (A, B, C, D, E)) chan Tuple5[A, B, C, D, E] { + ch := make(chan Tuple5[A, B, C, D, E]) + go func() { + ch <- T5(f()) + }() + return ch +} + +// Async6 has the same behavior as Async, but returns the 6 results as a tuple inside the channel. +func Async6[A any, B any, C any, D any, E any, F any](f func() (A, B, C, D, E, F)) chan Tuple6[A, B, C, D, E, F] { + ch := make(chan Tuple6[A, B, C, D, E, F]) + go func() { + ch <- T6(f()) + }() + return ch +} diff --git a/concurrency_test.go b/concurrency_test.go index c552a5b0..d07407e4 100644 --- a/concurrency_test.go +++ b/concurrency_test.go @@ -63,4 +63,94 @@ func TestAsyncX(t *testing.T) { is.Fail("Async1 should not block") } } + + { + sync := make(chan struct{}) + + ch := Async2(func() (int, string) { + <-sync + return 10, "Hello" + }) + + sync <- struct{}{} + + select { + case result := <-ch: + is.Equal(result, Tuple2[int, string]{10, "Hello"}) + case <-time.After(time.Millisecond): + is.Fail("Async2 should not block") + } + } + + { + sync := make(chan struct{}) + + ch := Async3(func() (int, string, bool) { + <-sync + return 10, "Hello", true + }) + + sync <- struct{}{} + + select { + case result := <-ch: + is.Equal(result, Tuple3[int, string, bool]{10, "Hello", true}) + case <-time.After(time.Millisecond): + is.Fail("Async3 should not block") + } + } + + { + sync := make(chan struct{}) + + ch := Async4(func() (int, string, bool, float64) { + <-sync + return 10, "Hello", true, 3.14 + }) + + sync <- struct{}{} + + select { + case result := <-ch: + is.Equal(result, Tuple4[int, string, bool, float64]{10, "Hello", true, 3.14}) + case <-time.After(time.Millisecond): + is.Fail("Async4 should not block") + } + } + + { + sync := make(chan struct{}) + + ch := Async5(func() (int, string, bool, float64, string) { + <-sync + return 10, "Hello", true, 3.14, "World" + }) + + sync <- struct{}{} + + select { + case result := <-ch: + is.Equal(result, Tuple5[int, string, bool, float64, string]{10, "Hello", true, 3.14, "World"}) + case <-time.After(time.Millisecond): + is.Fail("Async5 should not block") + } + } + + { + sync := make(chan struct{}) + + ch := Async6(func() (int, string, bool, float64, string, int) { + <-sync + return 10, "Hello", true, 3.14, "World", 100 + }) + + sync <- struct{}{} + + select { + case result := <-ch: + is.Equal(result, Tuple6[int, string, bool, float64, string, int]{10, "Hello", true, 3.14, "World", 100}) + case <-time.After(time.Millisecond): + is.Fail("Async6 should not block") + } + } }