mirror of
https://github.com/samber/lo.git
synced 2026-04-22 15:37:14 +08:00
Merge branch 'master' into master
This commit is contained in:
@@ -1,5 +1,69 @@
|
||||
# Changelog
|
||||
|
||||
## 1.10.0 (2022-03-11)
|
||||
|
||||
Adding:
|
||||
|
||||
- Try
|
||||
- Try{0-6}
|
||||
- TryWitchValue
|
||||
- TryCatch
|
||||
- TryCatchWitchValue
|
||||
- Debounce
|
||||
|
||||
## 1.10.0 (2022-03-11)
|
||||
|
||||
Adding:
|
||||
|
||||
- Range
|
||||
- RangeFrom
|
||||
- RangeWithSteps
|
||||
|
||||
## 1.9.0 (2022-03-10)
|
||||
|
||||
Added
|
||||
|
||||
- Drop
|
||||
- DropRight
|
||||
- DropWhile
|
||||
- DropRightWhile
|
||||
|
||||
## 1.8.0 (2022-03-10)
|
||||
|
||||
Adding Union.
|
||||
|
||||
## 1.7.0 (2022-03-09)
|
||||
|
||||
Adding ContainBy
|
||||
|
||||
Adding MapValues
|
||||
|
||||
Adding FlatMap
|
||||
|
||||
## 1.6.0 (2022-03-07)
|
||||
|
||||
Fixed PartitionBy.
|
||||
|
||||
Adding Sample
|
||||
|
||||
Adding Samples
|
||||
|
||||
## 1.5.0 (2022-03-07)
|
||||
|
||||
Adding Times
|
||||
|
||||
Adding Attempt
|
||||
|
||||
Adding Repeat
|
||||
|
||||
## 1.4.0 (2022-03-07)
|
||||
|
||||
- adding tuple types (2->9)
|
||||
- adding Zip + Unzip
|
||||
- adding lo.PartitionBy + lop.PartitionBy
|
||||
- adding lop.GroupBy
|
||||
- fixing Nth
|
||||
|
||||
## 1.3.0 (2022-03-03)
|
||||
|
||||
Last and Nth return errors
|
||||
|
||||
+1
-1
@@ -3,6 +3,6 @@ FROM golang:1.18rc1-bullseye
|
||||
|
||||
WORKDIR /go/src/github.com/samber/lo
|
||||
|
||||
COPY Makefile go.* /go/src/github.com/samber/lo/
|
||||
COPY Makefile go.* ./
|
||||
|
||||
RUN make tools
|
||||
|
||||
@@ -12,12 +12,12 @@ build:
|
||||
test:
|
||||
go test -race -v ./...
|
||||
watch-test:
|
||||
reflex -R assets.go -t 50ms -s -- sh -c 'gotest -race -v ./...'
|
||||
reflex -t 50ms -s -- sh -c 'gotest -race -v ./...'
|
||||
|
||||
bench:
|
||||
go test -benchmem -count 3 -bench ./...
|
||||
watch-bench:
|
||||
reflex -R assets.go -t 50ms -s -- sh -c 'go test -benchmem -count 3 -bench ./...'
|
||||
reflex -t 50ms -s -- sh -c 'go test -benchmem -count 3 -bench ./...'
|
||||
|
||||
coverage:
|
||||
${BIN} test -v -coverprofile cover.out .
|
||||
|
||||
@@ -64,12 +64,13 @@ Supported helpers for slices:
|
||||
- Reverse
|
||||
- Fill
|
||||
- Repeat
|
||||
- ToMap
|
||||
- KeyBy
|
||||
- Drop
|
||||
- DropRight
|
||||
- DropWhile
|
||||
- DropRightWhile
|
||||
- Reject
|
||||
- Range / RangeFrom / RangeWithSteps
|
||||
|
||||
Supported helpers for maps:
|
||||
|
||||
@@ -114,8 +115,18 @@ Other functional programming helpers:
|
||||
- Switch / Case / Default
|
||||
- ToPtr
|
||||
- ToSlicePtr
|
||||
|
||||
Time based helpers:
|
||||
|
||||
- Attempt
|
||||
- Range / RangeFrom / RangeWithSteps
|
||||
- Debounce
|
||||
|
||||
Error handling:
|
||||
|
||||
- Try
|
||||
- TryCatch
|
||||
- TryWithErrorValue
|
||||
- TryCatchWithErrorValue
|
||||
|
||||
Constraints:
|
||||
|
||||
@@ -406,15 +417,28 @@ initializedSlice := lo.Repeat[foo](2, foo{"a"})
|
||||
// []foo{foo{"a"}, foo{"a"}}
|
||||
```
|
||||
|
||||
### ToMap
|
||||
### KeyBy
|
||||
|
||||
Transforms a slice or an array of structs to a map based on a pivot callback.
|
||||
|
||||
```go
|
||||
m := lo.ToMap[int, string]([]string{"a", "aa", "aaa"}, func(str string) int {
|
||||
m := lo.KeyBy[int, string]([]string{"a", "aa", "aaa"}, func(str string) int {
|
||||
return len(str)
|
||||
})
|
||||
// map[int]string{1: "a", 2: "aa", 3: "aaa"}
|
||||
|
||||
type Character struct {
|
||||
dir string
|
||||
code int
|
||||
}
|
||||
characters := []Character{
|
||||
{dir: "left", code: 97},
|
||||
{dir: "right", code: 100},
|
||||
}
|
||||
result := lo.KeyBy[string, Character](characters, func(char Character) string {
|
||||
return string(rune(char.code))
|
||||
})
|
||||
//map[a:{dir:left code:97} d:{dir:right code:100}]
|
||||
```
|
||||
|
||||
### Drop
|
||||
@@ -443,7 +467,7 @@ Drop elements from the beginning of a slice or array while the predicate returns
|
||||
l := lo.DropWhile[string]([]string{"a", "aa", "aaa", "aa", "aa"}, func(val string) bool {
|
||||
return len(val) <= 2
|
||||
})
|
||||
// []string{"aaa", "aa", "a"}
|
||||
// []string{"aaa", "aa", "aa"}
|
||||
```
|
||||
|
||||
### DropRightWhile
|
||||
@@ -468,6 +492,36 @@ odd := lo.Reject[int]([]int{1, 2, 3, 4}, func(x int, _ int) bool {
|
||||
// []int{1, 3}
|
||||
```
|
||||
|
||||
### Range / RangeFrom / RangeWithSteps
|
||||
|
||||
Creates an array of numbers (positive and/or negative) progressing from start up to, but not including end.
|
||||
|
||||
```go
|
||||
result := Range(4)
|
||||
// [0, 1, 2, 3]
|
||||
|
||||
result := Range(-4);
|
||||
// [0, -1, -2, -3]
|
||||
|
||||
result := RangeFrom(1, 5);
|
||||
// [1, 2, 3, 4]
|
||||
|
||||
result := RangeFrom[float64](1.0, 5);
|
||||
// [1.0, 2.0, 3.0, 4.0]
|
||||
|
||||
result := RangeWithSteps(0, 20, 5);
|
||||
// [0, 5, 10, 15]
|
||||
|
||||
result := RangeWithSteps[float32](-1.0, -4.0, -1.0);
|
||||
// [-1.0, -2.0, -3.0]
|
||||
|
||||
result := RangeWithSteps(1, 4, -1);
|
||||
// []
|
||||
|
||||
result := Range(0);
|
||||
// []
|
||||
```
|
||||
|
||||
### Keys
|
||||
|
||||
Creates an array of the map keys.
|
||||
@@ -860,37 +914,103 @@ iter, err := lo.Attempt(0, func(i int) error {
|
||||
// nil
|
||||
```
|
||||
|
||||
### Range / RangeFrom / RangeWithSteps
|
||||
### Debounce
|
||||
|
||||
Creates an array of numbers (positive and/or negative) progressing from start up to, but not including end.
|
||||
`NewDebounce` creates a debounced instance that delays invoking functions given until after wait milliseconds have elapsed, until `cancel` is called.
|
||||
|
||||
```go
|
||||
result := Range(4)
|
||||
// [0, 1, 2, 3]
|
||||
f := func() {
|
||||
println("Called once after 100ms when debounce stopped invoking!")
|
||||
}
|
||||
|
||||
result := Range(-4);
|
||||
// [0, -1, -2, -3]
|
||||
debounce, cancel := lo.NewDebounce(100 * time.Millisecond, f)
|
||||
for j := 0; j < 10; j++ {
|
||||
debounce()
|
||||
}
|
||||
|
||||
result := RangeFrom(1, 5);
|
||||
// [1, 2, 3, 4]
|
||||
|
||||
result := RangeFrom[float64](1.0, 5);
|
||||
// [1.0, 2.0, 3.0, 4.0]
|
||||
|
||||
result := RangeWithSteps(0, 20, 5);
|
||||
// [0, 5, 10, 15]
|
||||
|
||||
result := RangeWithSteps[float32](-1.0, -4.0, -1.0);
|
||||
// [-1.0, -2.0, -3.0]
|
||||
|
||||
result := RangeWithSteps(1, 4, -1);
|
||||
// []
|
||||
|
||||
result := Range(0);
|
||||
// []
|
||||
time.Sleep(1 * time.Second)
|
||||
cancel()
|
||||
```
|
||||
|
||||
For more advanced retry strategies (delay, exponential backoff...), please take a look on [cenkalti/backoff](https://github.com/cenkalti/backoff).
|
||||
## Try
|
||||
|
||||
Calls the function and return false in case of error and on panic.
|
||||
|
||||
```go
|
||||
ok := lo.Try(func() error {
|
||||
panic("error")
|
||||
return nil
|
||||
})
|
||||
// false
|
||||
|
||||
ok := lo.Try(func() error {
|
||||
return nil
|
||||
})
|
||||
// true
|
||||
|
||||
ok := lo.Try(func() error {
|
||||
return fmt.Errorf("error")
|
||||
})
|
||||
// false
|
||||
```
|
||||
|
||||
## Try{0->6}
|
||||
|
||||
The same behavior than `Try`, but callback returns 2 variables.
|
||||
|
||||
```go
|
||||
ok := lo.Try2(func() (string, error) {
|
||||
panic("error")
|
||||
return "", nil
|
||||
})
|
||||
// false
|
||||
```
|
||||
|
||||
## TryWithErrorValue
|
||||
|
||||
The same behavior than `Try`, but also returns value passed to panic.
|
||||
|
||||
```go
|
||||
err, ok := lo.TryWithErrorValue(func() error {
|
||||
panic("error")
|
||||
return nil
|
||||
})
|
||||
// "error", false
|
||||
```
|
||||
|
||||
## TryCatch
|
||||
|
||||
The same behavior than `Try`, but calls the catch function in case of error.
|
||||
|
||||
```go
|
||||
caught := false
|
||||
|
||||
ok := lo.TryCatch(func() error {
|
||||
panic("error")
|
||||
return nil
|
||||
}, func() {
|
||||
caught = true
|
||||
})
|
||||
// false
|
||||
// caught == true
|
||||
```
|
||||
|
||||
## TryCatchWithErrorValue
|
||||
|
||||
The same behavior than `TryWithErrorValue`, but calls the catch function in case of error.
|
||||
|
||||
```go
|
||||
caught := false
|
||||
|
||||
ok := lo.TryCatchWithErrorValue(func() error {
|
||||
panic("error")
|
||||
return nil
|
||||
}, func(val any) {
|
||||
caught = val == "error"
|
||||
})
|
||||
// false
|
||||
// caught == true
|
||||
```
|
||||
|
||||
## 🛩 Benchmark
|
||||
|
||||
|
||||
@@ -69,4 +69,4 @@ func MapValues[K comparable, V any, R any](in map[K]V, iteratee func(V, K) R) ma
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,65 @@
|
||||
package lo
|
||||
|
||||
import (
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
type debounce struct {
|
||||
after time.Duration
|
||||
mu *sync.Mutex
|
||||
timer *time.Timer
|
||||
done bool
|
||||
callbacks []func()
|
||||
}
|
||||
|
||||
func (d *debounce) reset() *debounce {
|
||||
d.mu.Lock()
|
||||
defer d.mu.Unlock()
|
||||
|
||||
if d.done {
|
||||
return d
|
||||
}
|
||||
|
||||
if d.timer != nil {
|
||||
d.timer.Stop()
|
||||
}
|
||||
|
||||
d.timer = time.AfterFunc(d.after, func() {
|
||||
for _, f := range d.callbacks {
|
||||
f()
|
||||
}
|
||||
})
|
||||
return d
|
||||
}
|
||||
|
||||
func (d *debounce) cancel() {
|
||||
d.mu.Lock()
|
||||
defer d.mu.Unlock()
|
||||
|
||||
if d.timer != nil {
|
||||
d.timer.Stop()
|
||||
d.timer = nil
|
||||
}
|
||||
|
||||
d.done = true
|
||||
}
|
||||
|
||||
// NewDebounce creates a debounced instance that delays invoking functions given until after wait milliseconds have elapsed.
|
||||
func NewDebounce(duration time.Duration, f ...func()) (func(), func()) {
|
||||
d := &debounce{
|
||||
after: duration,
|
||||
mu: new(sync.Mutex),
|
||||
timer: nil,
|
||||
done: false,
|
||||
callbacks: f,
|
||||
}
|
||||
|
||||
return func() {
|
||||
d.reset()
|
||||
}, d.cancel
|
||||
}
|
||||
|
||||
// Attempt invokes a function N times until it returns valid output. Returning either the caught error or nil. When first argument is less than `1`, the function runs until a sucessfull response is returned.
|
||||
func Attempt(maxIteration int, f func(int) error) (int, error) {
|
||||
var err error
|
||||
@@ -16,4 +76,3 @@ func Attempt(maxIteration int, f func(int) error) (int, error) {
|
||||
}
|
||||
|
||||
// throttle ?
|
||||
// debounce ?
|
||||
|
||||
@@ -3,6 +3,7 @@ package lo
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
@@ -46,3 +47,49 @@ func TestAttempt(t *testing.T) {
|
||||
is.Equal(iter4, 43)
|
||||
is.Equal(err4, nil)
|
||||
}
|
||||
|
||||
func TestDebounce(t *testing.T) {
|
||||
f1 := func() {
|
||||
println("1. Called once after 10ms when func stopped invoking!")
|
||||
}
|
||||
f2 := func() {
|
||||
println("2. Called once after 10ms when func stopped invoking!")
|
||||
}
|
||||
f3 := func() {
|
||||
println("3. Called once after 10ms when func stopped invoking!")
|
||||
}
|
||||
|
||||
d1, _ := NewDebounce(10*time.Millisecond, f1)
|
||||
|
||||
// execute 3 times
|
||||
for i := 0; i < 3; i++ {
|
||||
for j := 0; j < 10; j++ {
|
||||
d1()
|
||||
}
|
||||
time.Sleep(20 * time.Millisecond)
|
||||
}
|
||||
|
||||
d2, _ := NewDebounce(10*time.Millisecond, f2)
|
||||
|
||||
// execute once because it is always invoked and only last invoke is worked after 100ms
|
||||
for i := 0; i < 3; i++ {
|
||||
for j := 0; j < 5; j++ {
|
||||
d2()
|
||||
}
|
||||
time.Sleep(5 * time.Millisecond)
|
||||
}
|
||||
|
||||
time.Sleep(10 * time.Millisecond)
|
||||
|
||||
// execute once because it is canceled after 200ms.
|
||||
d3, cancel := NewDebounce(10*time.Millisecond, f3)
|
||||
for i := 0; i < 3; i++ {
|
||||
for j := 0; j < 10; j++ {
|
||||
d3()
|
||||
}
|
||||
time.Sleep(20 * time.Millisecond)
|
||||
if i == 0 {
|
||||
cancel()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -229,8 +229,8 @@ func Repeat[T Clonable[T]](count int, initial T) []T {
|
||||
return result
|
||||
}
|
||||
|
||||
// ToMap transforms a slice or an array of structs to a map based on a pivot callback.
|
||||
func ToMap[K comparable, V any](collection []V, iteratee func(V) K) map[K]V {
|
||||
// KeyBy transforms a slice or an array of structs to a map based on a pivot callback.
|
||||
func KeyBy[K comparable, V any](collection []V, iteratee func(V) K) map[K]V {
|
||||
result := make(map[K]V, len(collection))
|
||||
|
||||
for _, v := range collection {
|
||||
|
||||
+2
-2
@@ -210,10 +210,10 @@ func TestRepeat(t *testing.T) {
|
||||
is.Equal(result2, []foo{})
|
||||
}
|
||||
|
||||
func TestToMap(t *testing.T) {
|
||||
func TestKeyBy(t *testing.T) {
|
||||
is := assert.New(t)
|
||||
|
||||
result1 := ToMap[int, string]([]string{"a", "aa", "aaa"}, func(str string) int {
|
||||
result1 := KeyBy[int, string]([]string{"a", "aa", "aaa"}, func(str string) int {
|
||||
return len(str)
|
||||
})
|
||||
|
||||
|
||||
@@ -0,0 +1,106 @@
|
||||
package lo
|
||||
|
||||
// Try calls the function and return false in case of error.
|
||||
func Try(callback func() error) (ok bool) {
|
||||
ok = true
|
||||
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
ok = false
|
||||
}
|
||||
}()
|
||||
|
||||
err := callback()
|
||||
if err != nil {
|
||||
ok = false
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// Try0 has the same behavior than Try, but callback returns no variable.
|
||||
func Try0[T any](callback func()) bool {
|
||||
return Try(func() error {
|
||||
callback()
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
// Try1 is an alias to Try
|
||||
func Try1[T any](callback func() error) bool {
|
||||
return Try(callback)
|
||||
}
|
||||
|
||||
// Try2 has the same behavior than Try, but callback returns 2 variables.
|
||||
func Try2[T any](callback func() (T, error)) bool {
|
||||
return Try(func() error {
|
||||
_, err := callback()
|
||||
return err
|
||||
})
|
||||
}
|
||||
|
||||
// Try3 has the same behavior than Try, but callback returns 3 variables.
|
||||
func Try3[T, R any](callback func() (T, R, error)) bool {
|
||||
return Try(func() error {
|
||||
_, _, err := callback()
|
||||
return err
|
||||
})
|
||||
}
|
||||
|
||||
// Try4 has the same behavior than Try, but callback returns 4 variables.
|
||||
func Try4[T, R, S any](callback func() (T, R, S, error)) bool {
|
||||
return Try(func() error {
|
||||
_, _, _, err := callback()
|
||||
return err
|
||||
})
|
||||
}
|
||||
|
||||
// Try5 has the same behavior than Try, but callback returns 5 variables.
|
||||
func Try5[T, R, S, Q any](callback func() (T, R, S, Q, error)) bool {
|
||||
return Try(func() error {
|
||||
_, _, _, _, err := callback()
|
||||
return err
|
||||
})
|
||||
}
|
||||
|
||||
// Try6 has the same behavior than Try, but callback returns 6 variables.
|
||||
func Try6[T, R, S, Q, U any](callback func() (T, R, S, Q, U, error)) bool {
|
||||
return Try(func() error {
|
||||
_, _, _, _, _, err := callback()
|
||||
return err
|
||||
})
|
||||
}
|
||||
|
||||
// TryWithErrorValue has the same behavior than Try, but also returns value passed to panic.
|
||||
func TryWithErrorValue(callback func() error) (errorValue any, ok bool) {
|
||||
ok = true
|
||||
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
ok = false
|
||||
errorValue = r
|
||||
}
|
||||
}()
|
||||
|
||||
err := callback()
|
||||
if err != nil {
|
||||
ok = false
|
||||
errorValue = err
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// TryCatch has the same behavior than Try, but calls the catch function in case of error.
|
||||
func TryCatch(callback func() error, catch func()) {
|
||||
if !Try(callback) {
|
||||
catch()
|
||||
}
|
||||
}
|
||||
|
||||
// TryCatchWithErrorValue has the same behavior than TryWithErrorValue, but calls the catch function in case of error.
|
||||
func TryCatchWithErrorValue(callback func() error, catch func(any)) {
|
||||
if err, ok := TryWithErrorValue(callback); !ok {
|
||||
catch(err)
|
||||
}
|
||||
}
|
||||
+156
@@ -0,0 +1,156 @@
|
||||
package lo
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestTry(t *testing.T) {
|
||||
is := assert.New(t)
|
||||
|
||||
is.False(Try(func() error {
|
||||
panic("error")
|
||||
return nil
|
||||
}))
|
||||
is.True(Try(func() error {
|
||||
return nil
|
||||
}))
|
||||
is.False(Try(func() error {
|
||||
return fmt.Errorf("fail")
|
||||
}))
|
||||
}
|
||||
|
||||
func TestTryFunctions(t *testing.T) {
|
||||
is := assert.New(t)
|
||||
|
||||
is.True(Try2(func() (string, error) {
|
||||
return "", nil
|
||||
}))
|
||||
|
||||
is.True(Try3(func() (string, string, error) {
|
||||
return "", "", nil
|
||||
}))
|
||||
|
||||
is.True(Try4(func() (string, string, string, error) {
|
||||
return "", "", "", nil
|
||||
}))
|
||||
|
||||
is.True(Try5(func() (string, string, string, string, error) {
|
||||
return "", "", "", "", nil
|
||||
}))
|
||||
|
||||
is.True(Try6(func() (string, string, string, string, string, error) {
|
||||
return "", "", "", "", "", nil
|
||||
}))
|
||||
|
||||
is.False(Try2(func() (string, error) {
|
||||
panic("error")
|
||||
return "", nil
|
||||
}))
|
||||
|
||||
is.False(Try3(func() (string, string, error) {
|
||||
panic("error")
|
||||
return "", "", nil
|
||||
}))
|
||||
|
||||
is.False(Try4(func() (string, string, string, error) {
|
||||
panic("error")
|
||||
return "", "", "", nil
|
||||
}))
|
||||
|
||||
is.False(Try5(func() (string, string, string, string, error) {
|
||||
panic("error")
|
||||
return "", "", "", "", nil
|
||||
}))
|
||||
|
||||
is.False(Try6(func() (string, string, string, string, string, error) {
|
||||
panic("error")
|
||||
return "", "", "", "", "", nil
|
||||
}))
|
||||
|
||||
is.False(Try2(func() (string, error) {
|
||||
return "", errors.New("foo")
|
||||
}))
|
||||
|
||||
is.False(Try3(func() (string, string, error) {
|
||||
return "", "", errors.New("foo")
|
||||
}))
|
||||
|
||||
is.False(Try4(func() (string, string, string, error) {
|
||||
return "", "", "", errors.New("foo")
|
||||
}))
|
||||
|
||||
is.False(Try5(func() (string, string, string, string, error) {
|
||||
return "", "", "", "", errors.New("foo")
|
||||
}))
|
||||
|
||||
is.False(Try6(func() (string, string, string, string, string, error) {
|
||||
return "", "", "", "", "", errors.New("foo")
|
||||
}))
|
||||
}
|
||||
|
||||
func TestTryWithErrorValue(t *testing.T) {
|
||||
is := assert.New(t)
|
||||
|
||||
err, ok := TryWithErrorValue(func() error {
|
||||
panic("error")
|
||||
return nil
|
||||
})
|
||||
is.False(ok)
|
||||
is.Equal("error", err)
|
||||
|
||||
err, ok = TryWithErrorValue(func() error {
|
||||
return nil
|
||||
})
|
||||
is.True(ok)
|
||||
is.Equal(nil, err)
|
||||
}
|
||||
|
||||
func TestTryCatch(t *testing.T) {
|
||||
is := assert.New(t)
|
||||
|
||||
caught := false
|
||||
TryCatch(func() error {
|
||||
panic("error")
|
||||
return nil
|
||||
}, func() {
|
||||
//error was caught
|
||||
caught = true
|
||||
})
|
||||
is.True(caught)
|
||||
|
||||
caught = false
|
||||
TryCatch(func() error {
|
||||
return nil
|
||||
}, func() {
|
||||
//no error to be caught
|
||||
caught = true
|
||||
})
|
||||
is.False(caught)
|
||||
}
|
||||
|
||||
func TestTryCatchWithErrorValue(t *testing.T) {
|
||||
is := assert.New(t)
|
||||
|
||||
caught := false
|
||||
TryCatchWithErrorValue(func() error {
|
||||
panic("error")
|
||||
return nil
|
||||
}, func(val any) {
|
||||
//error was caught
|
||||
caught = val == "error"
|
||||
})
|
||||
is.True(caught)
|
||||
|
||||
caught = false
|
||||
TryCatchWithErrorValue(func() error {
|
||||
return nil
|
||||
}, func(val any) {
|
||||
//no error to be caught
|
||||
caught = true
|
||||
})
|
||||
is.False(caught)
|
||||
}
|
||||
+11
-8
@@ -1,8 +1,9 @@
|
||||
package lo
|
||||
|
||||
import (
|
||||
"github.com/stretchr/testify/assert"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestRange(t *testing.T) {
|
||||
@@ -34,11 +35,13 @@ func TestRangeClose(t *testing.T) {
|
||||
result1 := RangeWithSteps(0, 20, 6)
|
||||
result2 := RangeWithSteps(0, 3, -5)
|
||||
result3 := RangeWithSteps(1, 1, 0)
|
||||
result4 := RangeWithSteps[float64](1.0, 4.0, 2.0)
|
||||
result5 := RangeWithSteps[float32](-1.0, -4.0, -1.0)
|
||||
is.Equal(result1, []int{0, 6, 12, 18})
|
||||
is.Equal(result2, []int{})
|
||||
is.Equal(result3, []int{})
|
||||
is.Equal(result4, []float64{1.0, 3.0})
|
||||
is.Equal(result5, []float32{-1.0, -2.0, -3.0})
|
||||
result4 := RangeWithSteps(3, 2, 1)
|
||||
result5 := RangeWithSteps[float64](1.0, 4.0, 2.0)
|
||||
result6 := RangeWithSteps[float32](-1.0, -4.0, -1.0)
|
||||
is.Equal([]int{0, 6, 12, 18}, result1)
|
||||
is.Equal([]int{}, result2)
|
||||
is.Equal([]int{}, result3)
|
||||
is.Equal([]int{}, result4)
|
||||
is.Equal([]float64{1.0, 3.0}, result5)
|
||||
is.Equal([]float32{-1.0, -2.0, -3.0}, result6)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user