lint: enable 7 more linters (#686)

* lint: enable and fix perfsprint issues

* lint: enable and fix nolintlint issues

* lint: enable and fix godot issues

* lint: enable and fix thelper issues

* lint: enable and fix tparallel issues

* lint: enable and fix paralleltest issues

* lint: enable and fix predeclared issues
This commit is contained in:
Nathan Baulch
2025-09-25 21:18:25 +10:00
committed by GitHub
parent 2911f93956
commit 1b92b5c7db
22 changed files with 299 additions and 229 deletions

View File

@@ -30,6 +30,13 @@ linters:
# - wsl_v5
- testifylint
- whitespace
- perfsprint
- nolintlint
- godot
- thelper
- tparallel
- paralleltest
- predeclared
# disable noisy/controversial ones which you might enable later
disable:

View File

@@ -2143,7 +2143,7 @@ duration := lo.Duration0(func() {
err, duration := lo.Duration1(func() error {
// very long job
return fmt.Errorf("an error")
return errors.New("an error")
})
// an error
// 3s
@@ -3752,7 +3752,7 @@ iter, err := lo.Attempt(42, func(i int) error {
return nil
}
return fmt.Errorf("failed")
return errors.New("failed")
})
// 6
// nil
@@ -3762,14 +3762,14 @@ iter, err := lo.Attempt(2, func(i int) error {
return nil
}
return fmt.Errorf("failed")
return errors.New("failed")
})
// 2
// error "failed"
iter, err := lo.Attempt(0, func(i int) error {
if i < 42 {
return fmt.Errorf("failed")
return errors.New("failed")
}
return nil
@@ -3794,7 +3794,7 @@ iter, duration, err := lo.AttemptWithDelay(5, 2*time.Second, func(i int, duratio
return nil
}
return fmt.Errorf("failed")
return errors.New("failed")
})
// 3
// ~ 4 seconds
@@ -4045,7 +4045,7 @@ transaction := NewTransaction().
fmt.Println("step 3")
if true {
return state, fmt.Errorf("error")
return state, errors.New("error")
}
return state + 42, nil
@@ -4239,7 +4239,7 @@ ok := lo.Try(func() error {
// true
ok := lo.Try(func() error {
return fmt.Errorf("error")
return errors.New("error")
})
// false
```
@@ -4279,7 +4279,7 @@ str, ok := lo.TryOr(func() error {
// true
str, ok := lo.TryOr(func() error {
return "hello", fmt.Errorf("error")
return "hello", errors.New("error")
}, "world")
// world
// false

View File

@@ -145,8 +145,8 @@ func DispatchingStrategyFirst[T any](msg T, index uint64, channels []<-chan T) i
func DispatchingStrategyLeast[T any](msg T, index uint64, channels []<-chan T) int {
seq := Range(len(channels))
return MinBy(seq, func(item int, min int) bool {
return len(channels[item]) < len(channels[min])
return MinBy(seq, func(item int, mIn int) bool {
return len(channels[item]) < len(channels[mIn])
})
}
@@ -156,8 +156,8 @@ func DispatchingStrategyLeast[T any](msg T, index uint64, channels []<-chan T) i
func DispatchingStrategyMost[T any](msg T, index uint64, channels []<-chan T) int {
seq := Range(len(channels))
return MaxBy(seq, func(item int, max int) bool {
return len(channels[item]) > len(channels[max]) && channelIsNotFull(channels[item])
return MaxBy(seq, func(item int, mAx int) bool {
return len(channels[item]) > len(channels[mAx]) && channelIsNotFull(channels[item])
})
}

View File

@@ -113,6 +113,7 @@ func TestDispatchingStrategyRoundRobin(t *testing.T) {
}
func TestDispatchingStrategyRandom(t *testing.T) {
t.Parallel()
testWithTimeout(t, 10*time.Millisecond)
is := assert.New(t)

View File

@@ -18,6 +18,7 @@ func TestTernary(t *testing.T) {
}
func TestTernaryF(t *testing.T) {
t.Parallel()
is := assert.New(t)
result1 := TernaryF(true, func() string { return "a" }, func() string { return "b" })

View File

@@ -1,6 +1,7 @@
package lo
import (
"errors"
"fmt"
)
@@ -31,10 +32,10 @@ func ExampleMust() {
Must(cb())
// will panic
Must(42, fmt.Errorf("my error"))
Must(42, errors.New("my error"))
// will panic with error message
Must(42, fmt.Errorf("world"), "hello")
Must(42, errors.New("world"), "hello")
}
func ExampleMust0() {
@@ -46,10 +47,10 @@ func ExampleMust0() {
Must0(nil)
// will panic
Must0(fmt.Errorf("my error"))
Must0(errors.New("my error"))
// will panic with error message
Must0(fmt.Errorf("world"), "hello")
Must0(errors.New("world"), "hello")
}
func ExampleMust1() {
@@ -67,10 +68,10 @@ func ExampleMust1() {
Must1(cb())
// will panic
Must1(42, fmt.Errorf("my error"))
Must1(42, errors.New("my error"))
// will panic with error message
Must1(42, fmt.Errorf("world"), "hello")
Must1(42, errors.New("world"), "hello")
}
func ExampleMust2() {
@@ -82,10 +83,10 @@ func ExampleMust2() {
Must2(42, "hello", nil)
// will panic
Must2(42, "hello", fmt.Errorf("my error"))
Must2(42, "hello", errors.New("my error"))
// will panic with error message
Must2(42, "hello", fmt.Errorf("world"), "hello")
Must2(42, "hello", errors.New("world"), "hello")
}
func ExampleMust3() {
@@ -97,10 +98,10 @@ func ExampleMust3() {
Must3(42, "hello", 4.2, nil)
// will panic
Must3(42, "hello", 4.2, fmt.Errorf("my error"))
Must3(42, "hello", 4.2, errors.New("my error"))
// will panic with error message
Must3(42, "hello", 4.2, fmt.Errorf("world"), "hello")
Must3(42, "hello", 4.2, errors.New("world"), "hello")
}
func ExampleMust4() {
@@ -112,10 +113,10 @@ func ExampleMust4() {
Must4(42, "hello", 4.2, true, nil)
// will panic
Must4(42, "hello", 4.2, true, fmt.Errorf("my error"))
Must4(42, "hello", 4.2, true, errors.New("my error"))
// will panic with error message
Must4(42, "hello", 4.2, true, fmt.Errorf("world"), "hello")
Must4(42, "hello", 4.2, true, errors.New("world"), "hello")
}
func ExampleMust5() {
@@ -127,10 +128,10 @@ func ExampleMust5() {
Must5(42, "hello", 4.2, true, foo{}, nil)
// will panic
Must5(42, "hello", 4.2, true, foo{}, fmt.Errorf("my error"))
Must5(42, "hello", 4.2, true, foo{}, errors.New("my error"))
// will panic with error message
Must5(42, "hello", 4.2, true, foo{}, fmt.Errorf("world"), "hello")
Must5(42, "hello", 4.2, true, foo{}, errors.New("world"), "hello")
}
func ExampleMust6() {
@@ -142,10 +143,10 @@ func ExampleMust6() {
Must5(42, "hello", 4.2, true, foo{}, "foobar", nil)
// will panic
Must5(42, "hello", 4.2, true, foo{}, "foobar", fmt.Errorf("my error"))
Must5(42, "hello", 4.2, true, foo{}, "foobar", errors.New("my error"))
// will panic with error message
Must5(42, "hello", 4.2, true, foo{}, "foobar", fmt.Errorf("world"), "hello")
Must5(42, "hello", 4.2, true, foo{}, "foobar", errors.New("world"), "hello")
}
func ExampleTry() {
@@ -153,7 +154,7 @@ func ExampleTry() {
return nil
})
ok2 := Try(func() error {
return fmt.Errorf("my error")
return errors.New("my error")
})
ok3 := Try(func() error {
panic("my error")
@@ -173,7 +174,7 @@ func ExampleTry1() {
return nil
})
ok2 := Try1(func() error {
return fmt.Errorf("my error")
return errors.New("my error")
})
ok3 := Try1(func() error {
panic("my error")
@@ -193,7 +194,7 @@ func ExampleTry2() {
return 42, nil
})
ok2 := Try2(func() (int, error) {
return 42, fmt.Errorf("my error")
return 42, errors.New("my error")
})
ok3 := Try2(func() (int, error) {
panic("my error")
@@ -213,7 +214,7 @@ func ExampleTry3() {
return 42, "foobar", nil
})
ok2 := Try3(func() (int, string, error) {
return 42, "foobar", fmt.Errorf("my error")
return 42, "foobar", errors.New("my error")
})
ok3 := Try3(func() (int, string, error) {
panic("my error")
@@ -233,7 +234,7 @@ func ExampleTry4() {
return 42, "foobar", 4.2, nil
})
ok2 := Try4(func() (int, string, float64, error) {
return 42, "foobar", 4.2, fmt.Errorf("my error")
return 42, "foobar", 4.2, errors.New("my error")
})
ok3 := Try4(func() (int, string, float64, error) {
panic("my error")
@@ -253,7 +254,7 @@ func ExampleTry5() {
return 42, "foobar", 4.2, true, nil
})
ok2 := Try5(func() (int, string, float64, bool, error) {
return 42, "foobar", 4.2, true, fmt.Errorf("my error")
return 42, "foobar", 4.2, true, errors.New("my error")
})
ok3 := Try5(func() (int, string, float64, bool, error) {
panic("my error")
@@ -273,7 +274,7 @@ func ExampleTry6() {
return 42, "foobar", 4.2, true, foo{}, nil
})
ok2 := Try6(func() (int, string, float64, bool, foo, error) {
return 42, "foobar", 4.2, true, foo{}, fmt.Errorf("my error")
return 42, "foobar", 4.2, true, foo{}, errors.New("my error")
})
ok3 := Try6(func() (int, string, float64, bool, foo, error) {
panic("my error")
@@ -293,7 +294,7 @@ func ExampleTryOr() {
return 42, nil
}, 21)
value2, ok2 := TryOr(func() (int, error) {
return 42, fmt.Errorf("my error")
return 42, errors.New("my error")
}, 21)
value3, ok3 := TryOr(func() (int, error) {
panic("my error")
@@ -313,7 +314,7 @@ func ExampleTryOr1() {
return 42, nil
}, 21)
value2, ok2 := TryOr1(func() (int, error) {
return 42, fmt.Errorf("my error")
return 42, errors.New("my error")
}, 21)
value3, ok3 := TryOr1(func() (int, error) {
panic("my error")
@@ -378,7 +379,7 @@ func ExampleTryWithErrorValue() {
return nil
})
err2, ok2 := TryWithErrorValue(func() error {
return fmt.Errorf("my error")
return errors.New("my error")
})
err3, ok3 := TryWithErrorValue(func() error {
panic("my error")

View File

@@ -2,13 +2,13 @@ package lo
import (
"errors"
"fmt"
"testing"
"github.com/stretchr/testify/assert"
)
func TestValidate(t *testing.T) {
t.Parallel()
is := assert.New(t)
slice := []string{"a"}
@@ -264,7 +264,7 @@ func TestTry(t *testing.T) {
return nil
}))
is.False(Try(func() error {
return fmt.Errorf("fail")
return errors.New("fail")
}))
}
@@ -587,7 +587,7 @@ func TestErrorsAs(t *testing.T) {
t.Parallel()
is := assert.New(t)
err, ok := ErrorsAs[*internalError](fmt.Errorf("hello world"))
err, ok := ErrorsAs[*internalError](errors.New("hello world"))
is.False(ok)
is.Nil(err)

120
find.go
View File

@@ -263,72 +263,72 @@ func FindDuplicatesBy[T any, U comparable, Slice ~[]T](collection Slice, iterate
// Returns zero value when the collection is empty.
// Play: https://go.dev/play/p/r6e-Z8JozS8
func Min[T constraints.Ordered](collection []T) T {
var min T
var mIn T
if len(collection) == 0 {
return min
return mIn
}
min = collection[0]
mIn = collection[0]
for i := 1; i < len(collection); i++ {
item := collection[i]
if item < min {
min = item
if item < mIn {
mIn = item
}
}
return min
return mIn
}
// MinIndex search the minimum value of a collection and the index of the minimum value.
// Returns (zero value, -1) when the collection is empty.
func MinIndex[T constraints.Ordered](collection []T) (T, int) {
var (
min T
mIn T
index int
)
if len(collection) == 0 {
return min, -1
return mIn, -1
}
min = collection[0]
mIn = collection[0]
for i := 1; i < len(collection); i++ {
item := collection[i]
if item < min {
min = item
if item < mIn {
mIn = item
index = i
}
}
return min, index
return mIn, index
}
// MinBy search the minimum value of a collection using the given comparison function.
// If several values of the collection are equal to the smallest value, returns the first such value.
// Returns zero value when the collection is empty.
func MinBy[T any](collection []T, comparison func(a T, b T) bool) T {
var min T
var mIn T
if len(collection) == 0 {
return min
return mIn
}
min = collection[0]
mIn = collection[0]
for i := 1; i < len(collection); i++ {
item := collection[i]
if comparison(item, min) {
min = item
if comparison(item, mIn) {
mIn = item
}
}
return min
return mIn
}
// MinIndexBy search the minimum value of a collection using the given comparison function and the index of the minimum value.
@@ -336,48 +336,48 @@ func MinBy[T any](collection []T, comparison func(a T, b T) bool) T {
// Returns (zero value, -1) when the collection is empty.
func MinIndexBy[T any](collection []T, comparison func(a T, b T) bool) (T, int) {
var (
min T
mIn T
index int
)
if len(collection) == 0 {
return min, -1
return mIn, -1
}
min = collection[0]
mIn = collection[0]
for i := 1; i < len(collection); i++ {
item := collection[i]
if comparison(item, min) {
min = item
if comparison(item, mIn) {
mIn = item
index = i
}
}
return min, index
return mIn, index
}
// Earliest search the minimum time.Time of a collection.
// Returns zero value when the collection is empty.
func Earliest(times ...time.Time) time.Time {
var min time.Time
var mIn time.Time
if len(times) == 0 {
return min
return mIn
}
min = times[0]
mIn = times[0]
for i := 1; i < len(times); i++ {
item := times[i]
if item.Before(min) {
min = item
if item.Before(mIn) {
mIn = item
}
}
return min
return mIn
}
// EarliestBy search the minimum time.Time of a collection using the given iteratee function.
@@ -408,72 +408,72 @@ func EarliestBy[T any](collection []T, iteratee func(item T) time.Time) T {
// Returns zero value when the collection is empty.
// Play: https://go.dev/play/p/r6e-Z8JozS8
func Max[T constraints.Ordered](collection []T) T {
var max T
var mAx T
if len(collection) == 0 {
return max
return mAx
}
max = collection[0]
mAx = collection[0]
for i := 1; i < len(collection); i++ {
item := collection[i]
if item > max {
max = item
if item > mAx {
mAx = item
}
}
return max
return mAx
}
// MaxIndex searches the maximum value of a collection and the index of the maximum value.
// Returns (zero value, -1) when the collection is empty.
func MaxIndex[T constraints.Ordered](collection []T) (T, int) {
var (
max T
mAx T
index int
)
if len(collection) == 0 {
return max, -1
return mAx, -1
}
max = collection[0]
mAx = collection[0]
for i := 1; i < len(collection); i++ {
item := collection[i]
if item > max {
max = item
if item > mAx {
mAx = item
index = i
}
}
return max, index
return mAx, index
}
// MaxBy search the maximum value of a collection using the given comparison function.
// If several values of the collection are equal to the greatest value, returns the first such value.
// Returns zero value when the collection is empty.
func MaxBy[T any](collection []T, comparison func(a T, b T) bool) T {
var max T
var mAx T
if len(collection) == 0 {
return max
return mAx
}
max = collection[0]
mAx = collection[0]
for i := 1; i < len(collection); i++ {
item := collection[i]
if comparison(item, max) {
max = item
if comparison(item, mAx) {
mAx = item
}
}
return max
return mAx
}
// MaxIndexBy search the maximum value of a collection using the given comparison function and the index of the maximum value.
@@ -481,48 +481,48 @@ func MaxBy[T any](collection []T, comparison func(a T, b T) bool) T {
// Returns (zero value, -1) when the collection is empty.
func MaxIndexBy[T any](collection []T, comparison func(a T, b T) bool) (T, int) {
var (
max T
mAx T
index int
)
if len(collection) == 0 {
return max, -1
return mAx, -1
}
max = collection[0]
mAx = collection[0]
for i := 1; i < len(collection); i++ {
item := collection[i]
if comparison(item, max) {
max = item
if comparison(item, mAx) {
mAx = item
index = i
}
}
return max, index
return mAx, index
}
// Latest search the maximum time.Time of a collection.
// Returns zero value when the collection is empty.
func Latest(times ...time.Time) time.Time {
var max time.Time
var mAx time.Time
if len(times) == 0 {
return max
return mAx
}
max = times[0]
mAx = times[0]
for i := 1; i < len(times); i++ {
item := times[i]
if item.After(max) {
max = item
if item.After(mAx) {
mAx = item
}
}
return max
return mAx
}
// LatestBy search the maximum time.Time of a collection using the given iteratee function.

View File

@@ -316,14 +316,14 @@ func TestMinBy(t *testing.T) {
t.Parallel()
is := assert.New(t)
result1 := MinBy([]string{"s1", "string2", "s3"}, func(item string, min string) bool {
return len(item) < len(min)
result1 := MinBy([]string{"s1", "string2", "s3"}, func(item string, mIn string) bool {
return len(item) < len(mIn)
})
result2 := MinBy([]string{"string1", "string2", "s3"}, func(item string, min string) bool {
return len(item) < len(min)
result2 := MinBy([]string{"string1", "string2", "s3"}, func(item string, mIn string) bool {
return len(item) < len(mIn)
})
result3 := MinBy([]string{}, func(item string, min string) bool {
return len(item) < len(min)
result3 := MinBy([]string{}, func(item string, mIn string) bool {
return len(item) < len(mIn)
})
is.Equal("s1", result1)
@@ -335,14 +335,14 @@ func TestMinIndexBy(t *testing.T) {
t.Parallel()
is := assert.New(t)
result1, index1 := MinIndexBy([]string{"s1", "string2", "s3"}, func(item string, min string) bool {
return len(item) < len(min)
result1, index1 := MinIndexBy([]string{"s1", "string2", "s3"}, func(item string, mIn string) bool {
return len(item) < len(mIn)
})
result2, index2 := MinIndexBy([]string{"string1", "string2", "s3"}, func(item string, min string) bool {
return len(item) < len(min)
result2, index2 := MinIndexBy([]string{"string1", "string2", "s3"}, func(item string, mIn string) bool {
return len(item) < len(mIn)
})
result3, index3 := MinIndexBy([]string{}, func(item string, min string) bool {
return len(item) < len(min)
result3, index3 := MinIndexBy([]string{}, func(item string, mIn string) bool {
return len(item) < len(mIn)
})
is.Equal("s1", result1)
@@ -435,14 +435,14 @@ func TestMaxBy(t *testing.T) {
t.Parallel()
is := assert.New(t)
result1 := MaxBy([]string{"s1", "string2", "s3"}, func(item string, max string) bool {
return len(item) > len(max)
result1 := MaxBy([]string{"s1", "string2", "s3"}, func(item string, mAx string) bool {
return len(item) > len(mAx)
})
result2 := MaxBy([]string{"string1", "string2", "s3"}, func(item string, max string) bool {
return len(item) > len(max)
result2 := MaxBy([]string{"string1", "string2", "s3"}, func(item string, mAx string) bool {
return len(item) > len(mAx)
})
result3 := MaxBy([]string{}, func(item string, max string) bool {
return len(item) > len(max)
result3 := MaxBy([]string{}, func(item string, mAx string) bool {
return len(item) > len(mAx)
})
is.Equal("string2", result1)
@@ -454,14 +454,14 @@ func TestMaxIndexBy(t *testing.T) {
t.Parallel()
is := assert.New(t)
result1, index1 := MaxIndexBy([]string{"s1", "string2", "s3"}, func(item string, max string) bool {
return len(item) > len(max)
result1, index1 := MaxIndexBy([]string{"s1", "string2", "s3"}, func(item string, mAx string) bool {
return len(item) > len(mAx)
})
result2, index2 := MaxIndexBy([]string{"string1", "string2", "s3"}, func(item string, max string) bool {
return len(item) > len(max)
result2, index2 := MaxIndexBy([]string{"string1", "string2", "s3"}, func(item string, mAx string) bool {
return len(item) > len(mAx)
})
result3, index3 := MaxIndexBy([]string{}, func(item string, max string) bool {
return len(item) > len(max)
result3, index3 := MaxIndexBy([]string{}, func(item string, mAx string) bool {
return len(item) > len(mAx)
})
is.Equal("string2", result1)
@@ -617,6 +617,8 @@ func TestNth(t *testing.T) {
}
func TestNthOr(t *testing.T) {
t.Parallel()
t.Run("Integers", func(t *testing.T) {
t.Parallel()
is := assert.New(t)
@@ -667,6 +669,8 @@ func TestNthOr(t *testing.T) {
}
func TestNthOrEmpty(t *testing.T) {
t.Parallel()
t.Run("Integers", func(t *testing.T) {
t.Parallel()
is := assert.New(t)

View File

@@ -1,7 +1,5 @@
//go:build !go1.22
//nolint:revive
package rand
import "math/rand"

View File

@@ -73,7 +73,7 @@ func BenchmarkMap(b *testing.B) {
})
}
// also apply to UniqValues
// @TODO: also apply to UniqValues.
func BenchmarkUniqKeys(b *testing.B) {
m := []map[int64]int64{
mapGenerator(100000),

View File

@@ -377,89 +377,127 @@ func TestMapValues(t *testing.T) {
is.Equal(map[int]string{1: "1", 2: "2", 3: "3", 4: "4"}, result2)
}
func mapEntriesTest[I any, O any](t *testing.T, in map[string]I, iteratee func(string, I) (string, O), expected map[string]O) {
is := assert.New(t)
result := MapEntries(in, iteratee)
is.Equal(expected, result)
}
func TestMapEntries(t *testing.T) {
mapEntriesTest(t, map[string]int{"foo": 1, "bar": 2}, func(k string, v int) (string, int) {
return k, v + 1
}, map[string]int{"foo": 2, "bar": 3})
mapEntriesTest(t, map[string]int{"foo": 1, "bar": 2}, func(k string, v int) (string, string) {
return k, k + strconv.Itoa(v)
}, map[string]string{"foo": "foo1", "bar": "bar2"})
mapEntriesTest(t, map[string]int{"foo": 1, "bar": 2}, func(k string, v int) (string, string) {
return k, strconv.Itoa(v) + k
}, map[string]string{"foo": "1foo", "bar": "2bar"})
t.Parallel()
// NoMutation
{
t.Run("Normal", func(t *testing.T) {
t.Parallel()
is := assert.New(t)
r1 := MapEntries(map[string]int{"foo": 1, "bar": 2},
func(k string, v int) (string, int) {
return k, v + 1
})
is.Equal(map[string]int{"foo": 2, "bar": 3}, r1)
r2 := MapEntries(map[string]int{"foo": 1, "bar": 2},
func(k string, v int) (string, string) {
return k, k + strconv.Itoa(v)
})
is.Equal(map[string]string{"foo": "foo1", "bar": "bar2"}, r2)
r3 := MapEntries(map[string]int{"foo": 1, "bar": 2},
func(k string, v int) (string, string) {
return k, strconv.Itoa(v) + k
})
is.Equal(map[string]string{"foo": "1foo", "bar": "2bar"}, r3)
})
t.Run("NoMutation", func(t *testing.T) {
t.Parallel()
r1 := map[string]int{"foo": 1, "bar": 2}
MapEntries(r1, func(k string, v int) (string, string) {
return k, strconv.Itoa(v) + "!!"
})
is.Equal(map[string]int{"foo": 1, "bar": 2}, r1)
}
// EmptyInput
{
mapEntriesTest(t, map[string]int{}, func(k string, v int) (string, string) {
assert.Equal(t, map[string]int{"foo": 1, "bar": 2}, r1)
})
t.Run("EmptyInput", func(t *testing.T) {
t.Parallel()
r1 := MapEntries(map[string]int{},
func(k string, v int) (string, string) {
return k, strconv.Itoa(v) + "!!"
}, map[string]string{})
})
assert.Empty(t, r1)
mapEntriesTest(t, map[string]any{}, func(k string, v any) (string, any) {
r2 := MapEntries(map[string]any{},
func(k string, v any) (string, any) {
return k, v
}, map[string]any{})
}
// Identity
{
mapEntriesTest(t, map[string]int{"foo": 1, "bar": 2}, func(k string, v int) (string, int) {
})
assert.Empty(t, r2)
})
t.Run("Identity", func(t *testing.T) {
t.Parallel()
r1 := MapEntries(map[string]int{"foo": 1, "bar": 2},
func(k string, v int) (string, int) {
return k, v
}, map[string]int{"foo": 1, "bar": 2})
mapEntriesTest(t, map[string]any{"foo": 1, "bar": "2", "ccc": true}, func(k string, v any) (string, any) {
})
assert.Equal(t, map[string]int{"foo": 1, "bar": 2}, r1)
r2 := MapEntries(map[string]any{"foo": 1, "bar": "2", "ccc": true},
func(k string, v any) (string, any) {
return k, v
}, map[string]any{"foo": 1, "bar": "2", "ccc": true})
}
// ToConstantEntry
{
mapEntriesTest(t, map[string]any{"foo": 1, "bar": "2", "ccc": true}, func(k string, v any) (string, any) {
})
assert.Equal(t, map[string]any{"foo": 1, "bar": "2", "ccc": true}, r2)
})
t.Run("ToConstantEntry", func(t *testing.T) {
t.Parallel()
r1 := MapEntries(map[string]any{"foo": 1, "bar": "2", "ccc": true},
func(k string, v any) (string, any) {
return "key", "value"
}, map[string]any{"key": "value"})
mapEntriesTest(t, map[string]any{"foo": 1, "bar": "2", "ccc": true}, func(k string, v any) (string, any) {
return "b", 5
}, map[string]any{"b": 5})
}
})
assert.Equal(t, map[string]any{"key": "value"}, r1)
r2 := MapEntries(map[string]any{"foo": 1, "bar": "2", "ccc": true},
func(k string, v any) (string, any) {
return "b", 5
})
assert.Equal(t, map[string]any{"b": 5}, r2)
})
//// OverlappingKeys
// // because using range over map, the order is not guaranteed
// // this test is not deterministic
//{
// mapEntriesTest(t, map[string]any{"foo": 1, "foo2": 2, "Foo": 2, "Foo2": "2", "bar": "2", "ccc": true}, func(k string, v any) (string, any) {
// t.Run("OverlappingKeys", func(t *testing.T) {
// t.Parallel()
//
// r1 := MapEntries(map[string]any{"foo": 1, "foo2": 2, "Foo": 2, "Foo2": "2", "bar": "2", "ccc": true},
// func(k string, v any) (string, any) {
// return string(k[0]), v
// }, map[string]any{"F": "2", "b": "2", "c": true, "f": 2})
// mapEntriesTest(t, map[string]string{"foo": "1", "foo2": "2", "Foo": "2", "Foo2": "2", "bar": "2", "ccc": "true"}, func(k string, v string) (string, string) {
// })
// assert.Equal(t, map[string]any{"F": "2", "b": "2", "c": true, "f": 1}, r1)
//
// r2 := MapEntries(map[string]string{"foo": "1", "foo2": "2", "Foo": "2", "Foo2": "2", "bar": "2", "ccc": "true"},
// func(k, v string) (string, string) {
// return v, k
// }, map[string]string{"1": "foo", "2": "bar", "true": "ccc"})
//}
// NormalMappers
{
mapEntriesTest(t, map[string]string{"foo": "1", "foo2": "2", "Foo": "2", "Foo2": "2", "bar": "2", "ccc": "true"}, func(k string, v string) (string, string) {
return k, k + v
}, map[string]string{"Foo": "Foo2", "Foo2": "Foo22", "bar": "bar2", "ccc": "ccctrue", "foo": "foo1", "foo2": "foo22"})
// })
// assert.Equal(t, map[string]string{"1": "foo", "2": "bar", "true": "ccc"}, r2)
// })
mapEntriesTest(t, map[string]struct {
t.Run("NormalMappers", func(t *testing.T) {
t.Parallel()
r1 := MapEntries(map[string]string{"foo": "1", "foo2": "2", "Foo": "2", "Foo2": "2", "bar": "2", "ccc": "true"},
func(k, v string) (string, string) {
return k, k + v
})
assert.Equal(t, map[string]string{"Foo": "Foo2", "Foo2": "Foo22", "bar": "bar2", "ccc": "ccctrue", "foo": "foo1", "foo2": "foo22"}, r1)
type myStruct struct {
name string
age int
}{"1-11-1": {name: "foo", age: 1}, "2-22-2": {name: "bar", age: 2}}, func(k string, v struct {
name string
age int
},
) (string, string) {
return v.name, k
}, map[string]string{"bar": "2-22-2", "foo": "1-11-1"})
}
r2 := MapEntries(map[string]myStruct{"1-11-1": {name: "foo", age: 1}, "2-22-2": {name: "bar", age: 2}},
func(k string, v myStruct) (string, string) {
return v.name, k
})
assert.Equal(t, map[string]string{"bar": "2-22-2", "foo": "1-11-1"}, r2)
})
}
func TestMapToSlice(t *testing.T) {
@@ -526,6 +564,7 @@ func BenchmarkAssign(b *testing.B) {
counts := []int{32768, 1024, 128, 32, 2}
allDifferentMap := func(b *testing.B, n int) []map[string]int {
b.Helper()
defer b.ResetTimer()
m := make([]map[string]int, 0)
for i := 0; i < n; i++ {
@@ -543,6 +582,7 @@ func BenchmarkAssign(b *testing.B) {
}
allTheSameMap := func(b *testing.B, n int) []map[string]int {
b.Helper()
defer b.ResetTimer()
m := make([]map[string]int, 0)
for i := 0; i < n; i++ {
@@ -563,7 +603,7 @@ func BenchmarkAssign(b *testing.B) {
differentMap := allDifferentMap(b, count)
sameMap := allTheSameMap(b, count)
b.Run(fmt.Sprintf("%d", count), func(b *testing.B) {
b.Run(strconv.Itoa(count), func(b *testing.B) {
testCases := []struct {
name string
in []map[string]int

10
math.go
View File

@@ -56,11 +56,11 @@ func RangeWithSteps[T constraints.Integer | constraints.Float](start, end, step
// Clamp clamps number within the inclusive lower and upper bounds.
// Play: https://go.dev/play/p/RU4lJNC2hlI
func Clamp[T constraints.Ordered](value T, min T, max T) T {
if value < min {
return min
} else if value > max {
return max
func Clamp[T constraints.Ordered](value T, mIn T, mAx T) T {
if value < mIn {
return mIn
} else if value > mAx {
return mAx
}
return value
}

View File

@@ -66,6 +66,7 @@ func TestClamp(t *testing.T) {
}
func TestSum(t *testing.T) {
t.Parallel()
is := assert.New(t)
result1 := Sum([]float32{2.3, 3.3, 4, 5.3})
@@ -99,6 +100,7 @@ func TestSumBy(t *testing.T) {
}
func TestProduct(t *testing.T) {
t.Parallel()
is := assert.New(t)
result1 := Product([]float32{2.3, 3.3, 4, 5.3})
@@ -121,6 +123,7 @@ func TestProduct(t *testing.T) {
}
func TestProductBy(t *testing.T) {
t.Parallel()
is := assert.New(t)
result1 := ProductBy([]float32{2.3, 3.3, 4, 5.3}, func(n float32) float32 { return n })

View File

@@ -10,6 +10,7 @@ import (
)
func TestMap(t *testing.T) {
t.Parallel()
is := assert.New(t)
result1 := Map([]int{1, 2, 3, 4}, func(x int, _ int) string {
@@ -24,6 +25,7 @@ func TestMap(t *testing.T) {
}
func TestForEach(t *testing.T) {
t.Parallel()
is := assert.New(t)
var counter uint64
@@ -36,6 +38,7 @@ func TestForEach(t *testing.T) {
}
func TestTimes(t *testing.T) {
t.Parallel()
is := assert.New(t)
result1 := Times(3, func(i int) string {
@@ -46,6 +49,7 @@ func TestTimes(t *testing.T) {
}
func TestGroupBy(t *testing.T) {
t.Parallel()
is := assert.New(t)
result1 := GroupBy([]int{0, 1, 2, 3, 4, 5}, func(i int) int {
@@ -72,6 +76,7 @@ func TestGroupBy(t *testing.T) {
}
func TestPartitionBy(t *testing.T) {
t.Parallel()
is := assert.New(t)
oddEven := func(x int) string {

View File

@@ -256,7 +256,7 @@ func NewTransaction[T any]() *Transaction[T] {
}
}
// Transaction implements a Saga pattern
// Transaction implements a Saga pattern.
type Transaction[T any] struct {
steps []transactionStep[T]
}

View File

@@ -4,6 +4,7 @@
package lo
import (
"errors"
"fmt"
"sync"
"sync/atomic"
@@ -85,7 +86,7 @@ func ExampleNewDebounceBy() {
func ExampleAttempt() {
count1, err1 := Attempt(2, func(i int) error {
if i == 0 {
return fmt.Errorf("error")
return errors.New("error")
}
return nil
@@ -93,7 +94,7 @@ func ExampleAttempt() {
count2, err2 := Attempt(2, func(i int) error {
if i < 10 {
return fmt.Errorf("error")
return errors.New("error")
}
return nil
@@ -109,7 +110,7 @@ func ExampleAttempt() {
func ExampleAttemptWithDelay() {
count1, time1, err1 := AttemptWithDelay(2, time.Millisecond, func(i int, _ time.Duration) error {
if i == 0 {
return fmt.Errorf("error")
return errors.New("error")
}
return nil
@@ -117,7 +118,7 @@ func ExampleAttemptWithDelay() {
count2, time2, err2 := AttemptWithDelay(2, time.Millisecond, func(i int, _ time.Duration) error {
if i < 10 {
return fmt.Errorf("error")
return errors.New("error")
}
return nil
@@ -157,7 +158,7 @@ func ExampleTransaction() {
fmt.Println("step 3")
if true {
return state, fmt.Errorf("error")
return state, errors.New("error")
}
return state + 42, nil
@@ -226,7 +227,7 @@ func ExampleTransaction_error() {
).
Then(
func(state int) (int, error) {
return state, fmt.Errorf("error")
return state, errors.New("error")
},
func(state int) int {
return state - 15

View File

@@ -1,7 +1,7 @@
package lo
import (
"fmt"
"errors"
"sync"
"testing"
"time"
@@ -13,7 +13,7 @@ func TestAttempt(t *testing.T) {
t.Parallel()
is := assert.New(t)
err := fmt.Errorf("failed")
err := errors.New("failed")
iter1, err1 := Attempt(42, func(i int) error {
return nil
@@ -54,7 +54,7 @@ func TestAttemptWithDelay(t *testing.T) {
t.Parallel()
is := assert.New(t)
err := fmt.Errorf("failed")
err := errors.New("failed")
iter1, dur1, err1 := AttemptWithDelay(42, 10*time.Millisecond, func(i int, d time.Duration) error {
return nil
@@ -100,9 +100,10 @@ func TestAttemptWithDelay(t *testing.T) {
}
func TestAttemptWhile(t *testing.T) {
t.Parallel()
is := assert.New(t)
err := fmt.Errorf("failed")
err := errors.New("failed")
iter1, err1 := AttemptWhile(42, func(i int) (error, bool) {
return nil, true
@@ -178,9 +179,10 @@ func TestAttemptWhile(t *testing.T) {
}
func TestAttemptWhileWithDelay(t *testing.T) {
t.Parallel()
is := assert.New(t)
err := fmt.Errorf("failed")
err := errors.New("failed")
iter1, dur1, err1 := AttemptWhileWithDelay(42, 10*time.Millisecond, func(i int, d time.Duration) (error, bool) {
return nil, true
@@ -405,6 +407,7 @@ func TestDebounceBy(t *testing.T) {
}
func TestTransaction(t *testing.T) {
t.Parallel()
is := assert.New(t)
// no error

View File

@@ -355,6 +355,7 @@ func TestFlatten(t *testing.T) {
}
func TestInterleave(t *testing.T) {
t.Parallel()
is := assert.New(t)
testCases := []struct {
@@ -394,8 +395,8 @@ func TestInterleave(t *testing.T) {
},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
tc := tc
t.Run(tc.name, func(t *testing.T) {
t.Parallel()
assert.Equal(t, tc.want, Interleave(tc.in...))
})
@@ -519,8 +520,8 @@ func TestAssociate(t *testing.T) {
},
}
for i, tc := range testCases {
t.Run(fmt.Sprintf("test_%d", i), func(t *testing.T) {
tc := tc
t.Run(fmt.Sprintf("test_%d", i), func(t *testing.T) {
t.Parallel()
assert.Equal(t, tc.want, Associate(tc.in, transform))
})
@@ -555,8 +556,8 @@ func TestSliceToMap(t *testing.T) {
},
}
for i, tc := range testCases {
t.Run(fmt.Sprintf("test_%d", i), func(t *testing.T) {
tc := tc
t.Run(fmt.Sprintf("test_%d", i), func(t *testing.T) {
t.Parallel()
assert.Equal(t, tc.want, SliceToMap(tc.in, transform))
})
@@ -591,8 +592,8 @@ func TestFilterSliceToMap(t *testing.T) {
},
}
for i, tc := range testCases {
t.Run(fmt.Sprintf("test_%d", i), func(t *testing.T) {
tc := tc
t.Run(fmt.Sprintf("test_%d", i), func(t *testing.T) {
t.Parallel()
assert.Equal(t, tc.want, FilterSliceToMap(tc.in, transform))
})

View File

@@ -108,6 +108,8 @@ func TestRuneLength(t *testing.T) {
}
func TestAllCase(t *testing.T) {
t.Parallel()
type output struct {
PascalCase string
CamelCase string
@@ -424,8 +426,8 @@ func TestAllCase(t *testing.T) {
}
for _, tc := range testCases {
t.Run(tc.in, func(t *testing.T) {
tc := tc
t.Run(tc.in, func(t *testing.T) {
t.Parallel()
is := assert.New(t)
is.Equalf(tc.want.PascalCase, PascalCase(tc.in), "PascalCase(%v)", tc.in)
@@ -437,6 +439,8 @@ func TestAllCase(t *testing.T) {
}
func TestWords(t *testing.T) {
t.Parallel()
testCases := []struct {
in string
want []string
@@ -451,8 +455,8 @@ func TestWords(t *testing.T) {
{"Int8Value", []string{"Int", "8", "Value"}},
}
for _, tc := range testCases {
t.Run(tc.in, func(t *testing.T) {
tc := tc
t.Run(tc.in, func(t *testing.T) {
t.Parallel()
assert.Equalf(t, tc.want, Words(tc.in), "Words(%v)", tc.in)
})
@@ -460,6 +464,8 @@ func TestWords(t *testing.T) {
}
func TestCapitalize(t *testing.T) {
t.Parallel()
testCases := []struct {
name string
in string
@@ -469,8 +475,8 @@ func TestCapitalize(t *testing.T) {
{"mixed case", "heLLO", "Hello"},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
tc := tc
t.Run(tc.name, func(t *testing.T) {
t.Parallel()
assert.Equalf(t, tc.want, Capitalize(tc.in), "Capitalize(%v)", tc.in)
})

View File

@@ -146,6 +146,7 @@ func TestToSlicePtr(t *testing.T) {
}
func TestFromSlicePtr(t *testing.T) {
t.Parallel()
is := assert.New(t)
str1 := "foo"
@@ -156,6 +157,7 @@ func TestFromSlicePtr(t *testing.T) {
}
func TestFromSlicePtrOr(t *testing.T) {
t.Parallel()
is := assert.New(t)
str1 := "foo"
@@ -197,7 +199,6 @@ func TestEmpty(t *testing.T) {
t.Parallel()
is := assert.New(t)
//nolint:unused
type test struct{}
is.Empty(Empty[string]())
@@ -212,7 +213,6 @@ func TestIsEmpty(t *testing.T) {
t.Parallel()
is := assert.New(t)
//nolint:unused
type test struct {
foobar string
}
@@ -229,7 +229,6 @@ func TestIsNotEmpty(t *testing.T) {
t.Parallel()
is := assert.New(t)
//nolint:unused
type test struct {
foobar string
}