diff --git a/README.md b/README.md index 9d37ed23..ec050cf5 100644 --- a/README.md +++ b/README.md @@ -165,7 +165,14 @@ Supported helpers for tuples: - [T2 -> T9](#t2---t9) - [Unpack2 -> Unpack9](#unpack2---unpack9) - [Zip2 -> Zip9](#zip2---zip9) +- [ZipBy2 -> ZipBy9](#zipby2---zipby9) - [Unzip2 -> Unzip9](#unzip2---unzip9) +- [UnzipBy2 -> UnzipBy9](#unzipby2---unzipby9) + +Supported helpers for time and duration: + +- [Duration](#duration) +- [Duration0 -> Duration10](#duration0-duration10) Supported helpers for channels: @@ -1508,6 +1515,44 @@ a, b := lo.UnzipBy2([]string{"hello", "john", "doe"}, func(str string) (string, // []int{5, 4, 3} ``` +### Duration + +Returns the time taken to execute a function. + +```go +duration := lo.Duration(func() { + // very long job +}) +// 3s +``` + +### Duration0 -> Duration10 + +Returns the time taken to execute a function. + +```go +duration := lo.Duration0(func() { + // very long job +}) +// 3s + +err, duration := lo.Duration1(func() error { + // very long job + return fmt.Errorf("an error") +}) +// an error +// 3s + +err, duration := lo.Duration3(func() (string, int, error) { + // very long job + return "hello", 42, nil +}) +// hello +// 42 +// nil +// 3s +``` + ### ChannelDispatcher Distributes messages from input channels into N child channels. Close events are propagated to children. diff --git a/time.go b/time.go new file mode 100644 index 00000000..e98e80f9 --- /dev/null +++ b/time.go @@ -0,0 +1,85 @@ +package lo + +import "time" + +// Duration returns the time taken to execute a function. +func Duration(cb func()) time.Duration { + return Duration0(cb) +} + +// Duration0 returns the time taken to execute a function. +func Duration0(cb func()) time.Duration { + start := time.Now() + cb() + return time.Since(start) +} + +// Duration1 returns the time taken to execute a function. +func Duration1[A any](cb func() A) (A, time.Duration) { + start := time.Now() + a := cb() + return a, time.Since(start) +} + +// Duration2 returns the time taken to execute a function. +func Duration2[A, B any](cb func() (A, B)) (A, B, time.Duration) { + start := time.Now() + a, b := cb() + return a, b, time.Since(start) +} + +// Duration3 returns the time taken to execute a function. +func Duration3[A, B, C any](cb func() (A, B, C)) (A, B, C, time.Duration) { + start := time.Now() + a, b, c := cb() + return a, b, c, time.Since(start) +} + +// Duration4 returns the time taken to execute a function. +func Duration4[A, B, C, D any](cb func() (A, B, C, D)) (A, B, C, D, time.Duration) { + start := time.Now() + a, b, c, d := cb() + return a, b, c, d, time.Since(start) +} + +// Duration5 returns the time taken to execute a function. +func Duration5[A, B, C, D, E any](cb func() (A, B, C, D, E)) (A, B, C, D, E, time.Duration) { + start := time.Now() + a, b, c, d, e := cb() + return a, b, c, d, e, time.Since(start) +} + +// Duration6 returns the time taken to execute a function. +func Duration6[A, B, C, D, E, F any](cb func() (A, B, C, D, E, F)) (A, B, C, D, E, F, time.Duration) { + start := time.Now() + a, b, c, d, e, f := cb() + return a, b, c, d, e, f, time.Since(start) +} + +// Duration7 returns the time taken to execute a function. +func Duration7[A, B, C, D, E, F, G any](cb func() (A, B, C, D, E, F, G)) (A, B, C, D, E, F, G, time.Duration) { + start := time.Now() + a, b, c, d, e, f, g := cb() + return a, b, c, d, e, f, g, time.Since(start) +} + +// Duration8 returns the time taken to execute a function. +func Duration8[A, B, C, D, E, F, G, H any](cb func() (A, B, C, D, E, F, G, H)) (A, B, C, D, E, F, G, H, time.Duration) { + start := time.Now() + a, b, c, d, e, f, g, h := cb() + return a, b, c, d, e, f, g, h, time.Since(start) +} + +// Duration9 returns the time taken to execute a function. +func Duration9[A, B, C, D, E, F, G, H, I any](cb func() (A, B, C, D, E, F, G, H, I)) (A, B, C, D, E, F, G, H, I, time.Duration) { + start := time.Now() + a, b, c, d, e, f, g, h, i := cb() + return a, b, c, d, e, f, g, h, i, time.Since(start) +} + +// Duration10 returns the time taken to execute a function. +func Duration10[A, B, C, D, E, F, G, H, I, J any](cb func() (A, B, C, D, E, F, G, H, I, J)) (A, B, C, D, E, F, G, H, I, J, time.Duration) { + start := time.Now() + a, b, c, d, e, f, g, h, i, j := cb() + return a, b, c, d, e, f, g, h, i, j, time.Since(start) +} diff --git a/time_test.go b/time_test.go new file mode 100644 index 00000000..3764fc78 --- /dev/null +++ b/time_test.go @@ -0,0 +1,149 @@ +package lo + +import ( + "testing" + "time" + + "github.com/stretchr/testify/assert" +) + +func TestDuration(t *testing.T) { + t.Parallel() + is := assert.New(t) + + result := Duration(func() { time.Sleep(10 * time.Millisecond) }) + is.InEpsilon(10*time.Millisecond, result, float64(2*time.Millisecond)) +} + +func TestDurationX(t *testing.T) { + t.Parallel() + is := assert.New(t) + + { + result := Duration0(func() { time.Sleep(10 * time.Millisecond) }) + is.InEpsilon(10*time.Millisecond, result, float64(2*time.Millisecond)) + } + + { + a, result := Duration1(func() string { time.Sleep(10 * time.Millisecond); return "a" }) + is.InEpsilon(10*time.Millisecond, result, float64(2*time.Millisecond)) + is.Equal("a", a) + } + + { + a, b, result := Duration2(func() (string, string) { time.Sleep(10 * time.Millisecond); return "a", "b" }) + is.InEpsilon(10*time.Millisecond, result, float64(2*time.Millisecond)) + is.Equal("a", a) + is.Equal("b", b) + } + + { + a, b, c, result := Duration3(func() (string, string, string) { time.Sleep(10 * time.Millisecond); return "a", "b", "c" }) + is.InEpsilon(10*time.Millisecond, result, float64(2*time.Millisecond)) + is.Equal("a", a) + is.Equal("b", b) + is.Equal("c", c) + } + + { + a, b, c, d, result := Duration4(func() (string, string, string, string) { time.Sleep(10 * time.Millisecond); return "a", "b", "c", "d" }) + is.InEpsilon(10*time.Millisecond, result, float64(2*time.Millisecond)) + is.Equal("a", a) + is.Equal("b", b) + is.Equal("c", c) + is.Equal("d", d) + } + + { + a, b, c, d, e, result := Duration5(func() (string, string, string, string, string) { + time.Sleep(10 * time.Millisecond) + return "a", "b", "c", "d", "e" + }) + is.InEpsilon(10*time.Millisecond, result, float64(2*time.Millisecond)) + is.Equal("a", a) + is.Equal("b", b) + is.Equal("c", c) + is.Equal("d", d) + is.Equal("e", e) + } + + { + a, b, c, d, e, f, result := Duration6(func() (string, string, string, string, string, string) { + time.Sleep(10 * time.Millisecond) + return "a", "b", "c", "d", "e", "f" + }) + is.InEpsilon(10*time.Millisecond, result, float64(2*time.Millisecond)) + is.Equal("a", a) + is.Equal("b", b) + is.Equal("c", c) + is.Equal("d", d) + is.Equal("e", e) + is.Equal("f", f) + } + + { + a, b, c, d, e, f, g, result := Duration7(func() (string, string, string, string, string, string, string) { + time.Sleep(10 * time.Millisecond) + return "a", "b", "c", "d", "e", "f", "g" + }) + is.InEpsilon(10*time.Millisecond, result, float64(2*time.Millisecond)) + is.Equal("a", a) + is.Equal("b", b) + is.Equal("c", c) + is.Equal("d", d) + is.Equal("e", e) + is.Equal("f", f) + is.Equal("g", g) + } + + { + a, b, c, d, e, f, g, h, result := Duration8(func() (string, string, string, string, string, string, string, string) { + time.Sleep(10 * time.Millisecond) + return "a", "b", "c", "d", "e", "f", "g", "h" + }) + is.InEpsilon(10*time.Millisecond, result, float64(2*time.Millisecond)) + is.Equal("a", a) + is.Equal("b", b) + is.Equal("c", c) + is.Equal("d", d) + is.Equal("e", e) + is.Equal("f", f) + is.Equal("g", g) + is.Equal("h", h) + } + + { + a, b, c, d, e, f, g, h, i, result := Duration9(func() (string, string, string, string, string, string, string, string, string) { + time.Sleep(10 * time.Millisecond) + return "a", "b", "c", "d", "e", "f", "g", "h", "i" + }) + is.InEpsilon(10*time.Millisecond, result, float64(2*time.Millisecond)) + is.Equal("a", a) + is.Equal("b", b) + is.Equal("c", c) + is.Equal("d", d) + is.Equal("e", e) + is.Equal("f", f) + is.Equal("g", g) + is.Equal("h", h) + is.Equal("i", i) + } + + { + a, b, c, d, e, f, g, h, i, j, result := Duration10(func() (string, string, string, string, string, string, string, string, string, string) { + time.Sleep(10 * time.Millisecond) + return "a", "b", "c", "d", "e", "f", "g", "h", "i", "j" + }) + is.InEpsilon(10*time.Millisecond, result, float64(2*time.Millisecond)) + is.Equal("a", a) + is.Equal("b", b) + is.Equal("c", c) + is.Equal("d", d) + is.Equal("e", e) + is.Equal("f", f) + is.Equal("g", g) + is.Equal("h", h) + is.Equal("i", i) + is.Equal("j", j) + } +}