From cfa77122f9bb24f336cc802c7e11feded275b924 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 27 Apr 2025 18:21:47 +0000 Subject: [PATCH] build(deps): bump github.com/samber/lo Bumps the production-dependencies group with 1 update: [github.com/samber/lo](https://github.com/samber/lo). Updates `github.com/samber/lo` from 1.49.1 to 1.50.0 - [Release notes](https://github.com/samber/lo/releases) - [Commits](https://github.com/samber/lo/compare/v1.49.1...v1.50.0) --- updated-dependencies: - dependency-name: github.com/samber/lo dependency-version: 1.50.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: production-dependencies ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 +- vendor/github.com/samber/lo/README.md | 157 ++++++++++++++++++- vendor/github.com/samber/lo/condition.go | 1 + vendor/github.com/samber/lo/find.go | 23 +++ vendor/github.com/samber/lo/intersect.go | 38 +++++ vendor/github.com/samber/lo/map.go | 17 ++ vendor/github.com/samber/lo/mutable/slice.go | 52 +++++- vendor/github.com/samber/lo/slice.go | 23 ++- vendor/github.com/samber/lo/string.go | 5 +- vendor/modules.txt | 2 +- 11 files changed, 305 insertions(+), 19 deletions(-) diff --git a/go.mod b/go.mod index 8b1c780..d79ad2f 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.24 require ( github.com/bradleyjkemp/cupaloy v2.3.0+incompatible github.com/google/go-cmp v0.7.0 - github.com/samber/lo v1.49.1 + github.com/samber/lo v1.50.0 github.com/stretchr/testify v1.10.0 golang.org/x/crypto v0.37.0 golang.org/x/text v0.24.0 diff --git a/go.sum b/go.sum index 89bb2cd..221942d 100644 --- a/go.sum +++ b/go.sum @@ -10,8 +10,8 @@ github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWb github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/samber/lo v1.49.1 h1:4BIFyVfuQSEpluc7Fua+j1NolZHiEHEpaSEKdsH0tew= -github.com/samber/lo v1.49.1/go.mod h1:dO6KHFzUKXgP8LDhU0oI8d2hekjXnGOu0DB8Jecxd6o= +github.com/samber/lo v1.50.0 h1:XrG0xOeHs+4FQ8gJR97zDz5uOFMW7OwFWiFVzqopKgY= +github.com/samber/lo v1.50.0/go.mod h1:RjZyNk6WSnUFRKK6EyOhsRJMqft3G+pg7dCWHQCWvsc= github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= golang.org/x/crypto v0.37.0 h1:kJNSjF/Xp7kU0iB2Z+9viTPMW4EqqsrywMXLJOOsXSE= diff --git a/vendor/github.com/samber/lo/README.md b/vendor/github.com/samber/lo/README.md index a3526a4..62e3bc8 100644 --- a/vendor/github.com/samber/lo/README.md +++ b/vendor/github.com/samber/lo/README.md @@ -49,6 +49,7 @@ You can import `lo` using: import ( "github.com/samber/lo" lop "github.com/samber/lo/parallel" + lom "github.com/samber/lo/mutable" ) ``` @@ -92,6 +93,7 @@ Supported helpers for slices: - [Uniq](#uniq) - [UniqBy](#uniqby) - [GroupBy](#groupby) +- [GroupByMap](#groupbymap) - [Chunk](#chunk) - [PartitionBy](#partitionby) - [Flatten](#flatten) @@ -148,6 +150,7 @@ Supported helpers for maps: - [MapValues](#mapvalues) - [MapEntries](#mapentries) - [MapToSlice](#maptoslice) +- [FilterMapToSlice](#FilterMapToSlice) Supported math helpers: @@ -218,6 +221,8 @@ Supported intersection helpers: - [WithoutBy](#withoutby) - [WithoutEmpty](#withoutempty) - [WithoutNth](#withoutnth) +- [ElementsMatch](#ElementsMatch) +- [ElementsMatchBy](#ElementsMatchBy) Supported search helpers: @@ -252,6 +257,8 @@ Supported search helpers: - [LastOrEmpty](#LastOrEmpty) - [LastOr](#LastOr) - [Nth](#nth) +- [NthOr](#nthor) +- [NthOrEmpty](#nthorempty) - [Sample](#sample) - [SampleBy](#sampleby) - [Samples](#samples) @@ -341,6 +348,23 @@ even := lo.Filter([]int{1, 2, 3, 4}, func(x int, index int) bool { [[play](https://go.dev/play/p/Apjg3WeSi7K)] +Mutable: like `lo.Filter()`, but the slice is updated in place. + +```go +import lom "github.com/samber/lo/mutable" + +list := []int{1, 2, 3, 4} +newList := lom.Filter(list, func(x int) bool { + return x%2 == 0 +}) + +list +// []int{2, 4, 3, 4} + +newList +// []int{2, 4} +``` + ### Map Manipulates a slice of one type and transforms it into a slice of another type: @@ -367,6 +391,18 @@ lop.Map([]int64{1, 2, 3, 4}, func(x int64, _ int) string { // []string{"1", "2", "3", "4"} ``` +Mutable: like `lo.Map()`, but the slice is updated in place. + +```go +import lom "github.com/samber/lo/mutable" + +list := []int{1, 2, 3, 4} +lom.Map(list, func(x int) int { + return i*2 +}) +// []int{2, 4, 6, 8} +``` + ### UniqMap Manipulates a slice and transforms it to a slice of another type with unique values. @@ -566,6 +602,19 @@ lop.GroupBy([]int{0, 1, 2, 3, 4, 5}, func(i int) int { // map[int][]int{0: []int{0, 3}, 1: []int{1, 4}, 2: []int{2, 5}} ``` +### GroupByMap + +Returns an object composed of keys generated from the results of running each element of collection through iteratee. + +```go +import lo "github.com/samber/lo" + +groups := lo.GroupByMap([]int{0, 1, 2, 3, 4, 5}, func(i int) (int, int) { + return i%3, i*2 +}) +// map[int][]int{0: []int{0, 6}, 1: []int{2, 8}, 2: []int{4, 10}} +``` + ### Chunk Returns an array of elements split into groups the length of size. If array can't be split evenly, the final chunk will be the remaining elements. @@ -656,11 +705,14 @@ Returns an array of shuffled values. Uses the Fisher-Yates shuffle algorithm. ```go import lom "github.com/samber/lo/mutable" -randomOrder := lom.Shuffle([]int{0, 1, 2, 3, 4, 5}) +list := []int{0, 1, 2, 3, 4, 5} +lom.Shuffle(list) + +list // []int{1, 4, 0, 3, 5, 2} ``` -[[play](https://go.dev/play/p/ZTGG7OUCdnp)] +[[play](https://go.dev/play/p/2xb3WdLjeSJ)] ### Reverse @@ -678,7 +730,7 @@ list // []int{5, 4, 3, 2, 1, 0} ``` -[[play](https://go.dev/play/p/iv2e9jslfBM)] +[[play](https://go.dev/play/p/O-M5pmCRgzV)] ### Fill @@ -1377,6 +1429,7 @@ maps := lo.ChunkEntries( // {"d": 4, "e": 5}, // } ``` +[[play](https://go.dev/play/p/X_YQL6mmoD-)] ### MapKeys @@ -1436,6 +1489,21 @@ s := lo.MapToSlice(m, func(k int, v int64) string { [[play](https://go.dev/play/p/ZuiCZpDt6LD)] +### FilterMapToSlice + +Transforms a map into a slice based on specific iteratee. The iteratee returns a value and a boolean. If the boolean is true, the value is added to the result slice. + +If the boolean is false, the value is not added to the result slice. The order of the keys in the input map is not specified and the order of the keys in the output slice is not guaranteed. + +```go +kv := map[int]int64{1: 1, 2: 2, 3: 3, 4: 4} + +result := lo.FilterMapToSlice(kv, func(k int, v int64) (string, bool) { + return fmt.Sprintf("%d_%d", k, v), k%2 == 0 +}) +// []{"2_2", "4_4"} +``` + ### Range / RangeFrom / RangeWithSteps Creates an array of numbers (positive and/or negative) progressing from start up to, but not including end. @@ -2334,6 +2402,36 @@ subset := lo.WithoutNth([]int{-2, -1, 0, 1, 2}, 3, -42, 1) // []int{-2, 0, 2} ``` +### ElementsMatch + +Returns true if lists contain the same set of elements (including empty set). + +If there are duplicate elements, the number of appearances of each of them in both lists should match. + +The order of elements is not checked. + +```go +b := lo.ElementsMatch([]int{1, 1, 2}, []int{2, 1, 1}) +// true +``` + +### ElementsMatchBy + +Returns true if lists contain the same set of elements' keys (including empty set). + +If there are duplicate keys, the number of appearances of each of them in both lists should match. + +The order of elements is not checked. + +```go +b := lo.ElementsMatchBy( + []someType{a, b}, + []someType{b, a}, + func(item someType) string { return item.ID() }, +) +// true +``` + ### IndexOf Returns the index at which the first occurrence of a value is found in an array or return -1 if the value cannot be found. @@ -2786,6 +2884,40 @@ nth, err := lo.Nth([]int{0, 1, 2, 3}, -2) // 2 ``` +### NthOr + +Returns the element at index `nth` of the collection. If `nth` is negative, it returns the `nth` element from the end. If `nth` is out of slice bounds, it returns the provided fallback value +```go +nth := lo.NthOr([]int{10, 20, 30, 40, 50}, 2, -1) +// 30 + +nth := lo.NthOr([]int{10, 20, 30, 40, 50}, -1, -1) +// 50 + +nth := lo.NthOr([]int{10, 20, 30, 40, 50}, 5, -1) +// -1 (fallback value) +``` + +### NthOrEmpty + +Returns the element at index `nth` of the collection. If `nth` is negative, it returns the `nth` element from the end. If `nth` is out of slice bounds, it returns the zero value for the element type (e.g., 0 for integers, "" for strings, etc). +``` go +nth := lo.NthOrEmpty([]int{10, 20, 30, 40, 50}, 2) +// 30 + +nth := lo.NthOrEmpty([]int{10, 20, 30, 40, 50}, -1) +// 50 + +nth := lo.NthOrEmpty([]int{10, 20, 30, 40, 50}, 5) +// 0 (zero value for int) + +nth := lo.NthOrEmpty([]string{"apple", "banana", "cherry"}, 2) +// "cherry" + +nth := lo.NthOrEmpty([]string{"apple", "banana", "cherry"}, 5) +// "" (zero value for string) +``` + ### Sample Returns a random item from collection. @@ -2798,6 +2930,8 @@ lo.Sample([]string{}) // "" ``` + + ### SampleBy Returns a random item from collection, using a given random integer generator. @@ -2836,6 +2970,7 @@ lo.SamplesBy([]string{"a", "b", "c"}, 3, r.Intn) A 1 line if/else statement. + ```go result := lo.Ternary(true, "a", "b") // "a" @@ -2844,6 +2979,8 @@ result := lo.Ternary(false, "a", "b") // "b" ``` +Take care to avoid dereferencing potentially nil pointers in your A/B expressions, because they are both evaluated. See TernaryF to avoid this problem. + [[play](https://go.dev/play/p/t-D7WBL44h2)] ### TernaryF @@ -3248,6 +3385,10 @@ result, ok := lo.CoalesceSlice([]int{1, 2, 3}, []int{4, 5, 6}) result, ok := lo.CoalesceSlice(nil, []int{}) // [] // true + +result, ok := lo.CoalesceSlice([]int(nil)) +// [] +// false ``` ### CoalesceSliceOrEmpty @@ -3268,12 +3409,16 @@ Returns the first non-zero map. ```go result, ok := lo.CoalesceMap(map[string]int{"1": 1, "2": 2, "3": 3}, map[string]int{"4": 4, "5": 5, "6": 6}) -// [1, 2, 3] +// {"1": 1, "2": 2, "3": 3} // true result, ok := lo.CoalesceMap(nil, map[string]int{}) -// [] +// {} // true + +result, ok := lo.CoalesceMap(map[string]int(nil)) +// {} +// false ``` ### CoalesceMapOrEmpty @@ -3986,7 +4131,7 @@ ok github.com/samber/lo 6.657s ``` - `lo.Map` is way faster (x7) than `go-funk`, a reflection-based Map implementation. -- `lo.Map` have the same allocation profile than `for`. +- `lo.Map` has the same allocation profile as `for`. - `lo.Map` is 4% slower than `for`. - `lop.Map` is slower than `lo.Map` because it implies more memory allocation and locks. `lop.Map` will be useful for long-running callbacks, such as i/o bound processing. - `for` beats other implementations for memory and CPU. diff --git a/vendor/github.com/samber/lo/condition.go b/vendor/github.com/samber/lo/condition.go index 1d4e75d..eaeaa2b 100644 --- a/vendor/github.com/samber/lo/condition.go +++ b/vendor/github.com/samber/lo/condition.go @@ -1,6 +1,7 @@ package lo // Ternary is a 1 line if/else statement. +// Take care to avoid dereferencing potentially nil pointers in your A/B expressions, because they are both evaluated. See TernaryF to avoid this problem. // Play: https://go.dev/play/p/t-D7WBL44h2 func Ternary[T any](condition bool, ifOutput T, elseOutput T) T { if condition { diff --git a/vendor/github.com/samber/lo/find.go b/vendor/github.com/samber/lo/find.go index 5d1b986..f04dc08 100644 --- a/vendor/github.com/samber/lo/find.go +++ b/vendor/github.com/samber/lo/find.go @@ -579,6 +579,29 @@ func Nth[T any, N constraints.Integer](collection []T, nth N) (T, error) { return collection[l+n], nil } +// NthOr returns the element at index `nth` of collection. +// If `nth` is negative, it returns the nth element from the end. +// If `nth` is out of slice bounds, it returns the fallback value instead of an error. +func NthOr[T any, N constraints.Integer](collection []T, nth N, fallback T) T { + value, err := Nth(collection, nth) + if err != nil { + return fallback + } + return value +} + +// NthOrEmpty returns the element at index `nth` of collection. +// If `nth` is negative, it returns the nth element from the end. +// If `nth` is out of slice bounds, it returns the zero value (empty value) for that type. +func NthOrEmpty[T any, N constraints.Integer](collection []T, nth N) T { + value, err := Nth(collection, nth) + if err != nil { + var zeroValue T + return zeroValue + } + return value +} + // randomIntGenerator is a function that should return a random integer in the range [0, n) // where n is the parameter passed to the randomIntGenerator. type randomIntGenerator func(n int) int diff --git a/vendor/github.com/samber/lo/intersect.go b/vendor/github.com/samber/lo/intersect.go index 7206245..c57bd81 100644 --- a/vendor/github.com/samber/lo/intersect.go +++ b/vendor/github.com/samber/lo/intersect.go @@ -225,3 +225,41 @@ func WithoutNth[T comparable, Slice ~[]T](collection Slice, nths ...int) Slice { return result } + +// ElementsMatch returns true if lists contain the same set of elements (including empty set). +// If there are duplicate elements, the number of appearances of each of them in both lists should match. +// The order of elements is not checked. +func ElementsMatch[T comparable, Slice ~[]T](list1 Slice, list2 Slice) bool { + return ElementsMatchBy(list1, list2, func(item T) T { return item }) +} + +// ElementsMatchBy returns true if lists contain the same set of elements' keys (including empty set). +// If there are duplicate keys, the number of appearances of each of them in both lists should match. +// The order of elements is not checked. +func ElementsMatchBy[T any, K comparable](list1 []T, list2 []T, iteratee func(item T) K) bool { + if len(list1) != len(list2) { + return false + } + + if len(list1) == 0 { + return true + } + + counters := make(map[K]int, len(list1)) + + for _, el := range list1 { + counters[iteratee(el)]++ + } + + for _, el := range list2 { + counters[iteratee(el)]-- + } + + for _, count := range counters { + if count != 0 { + return false + } + } + + return true +} diff --git a/vendor/github.com/samber/lo/map.go b/vendor/github.com/samber/lo/map.go index b1959e2..6febb3f 100644 --- a/vendor/github.com/samber/lo/map.go +++ b/vendor/github.com/samber/lo/map.go @@ -249,6 +249,7 @@ func Assign[K comparable, V any, Map ~map[K]V](maps ...Map) Map { // ChunkEntries splits a map into an array of elements in groups of a length equal to its size. If the map cannot be split evenly, // the final chunk will contain the remaining elements. +// Play: https://go.dev/play/p/X_YQL6mmoD- func ChunkEntries[K comparable, V any](m map[K]V, size int) []map[K]V { if size <= 0 { panic("The chunk size must be greater than 0") @@ -325,3 +326,19 @@ func MapToSlice[K comparable, V any, R any](in map[K]V, iteratee func(key K, val return result } + +// FilterMapToSlice transforms a map into a slice based on specific iteratee. +// The iteratee returns a value and a boolean. If the boolean is true, the value is added to the result slice. +// If the boolean is false, the value is not added to the result slice. +// The order of the keys in the input map is not specified and the order of the keys in the output slice is not guaranteed. +func FilterMapToSlice[K comparable, V any, R any](in map[K]V, iteratee func(key K, value V) (R, bool)) []R { + result := make([]R, 0, len(in)) + + for k := range in { + if v, ok := iteratee(k, in[k]); ok { + result = append(result, v) + } + } + + return result +} diff --git a/vendor/github.com/samber/lo/mutable/slice.go b/vendor/github.com/samber/lo/mutable/slice.go index 6d61fa7..969f399 100644 --- a/vendor/github.com/samber/lo/mutable/slice.go +++ b/vendor/github.com/samber/lo/mutable/slice.go @@ -2,8 +2,56 @@ package mutable import "github.com/samber/lo/internal/rand" +// Filter is a generic function that modifies the input slice in-place to contain only the elements +// that satisfy the provided predicate function. The predicate function takes an element of the slice and its index, +// and should return true for elements that should be kept and false for elements that should be removed. +// The function returns the modified slice, which may be shorter than the original if some elements were removed. +// Note that the order of elements in the original slice is preserved in the output. +func Filter[T any, Slice ~[]T](collection Slice, predicate func(item T) bool) Slice { + j := 0 + for _, item := range collection { + if predicate(item) { + collection[j] = item + j++ + } + } + return collection[:j] +} + +// FilterI is a generic function that modifies the input slice in-place to contain only the elements +// that satisfy the provided predicate function. The predicate function takes an element of the slice and its index, +// and should return true for elements that should be kept and false for elements that should be removed. +// The function returns the modified slice, which may be shorter than the original if some elements were removed. +// Note that the order of elements in the original slice is preserved in the output. +func FilterI[T any, Slice ~[]T](collection Slice, predicate func(item T, index int) bool) Slice { + j := 0 + for i, item := range collection { + if predicate(item, i) { + collection[j] = item + j++ + } + } + return collection[:j] +} + +// Map is a generic function that modifies the input slice in-place to contain the result of applying the provided +// function to each element of the slice. The function returns the modified slice, which has the same length as the original. +func Map[T any, Slice ~[]T](collection Slice, fn func(item T) T) { + for i := range collection { + collection[i] = fn(collection[i]) + } +} + +// MapI is a generic function that modifies the input slice in-place to contain the result of applying the provided +// function to each element of the slice. The function returns the modified slice, which has the same length as the original. +func MapI[T any, Slice ~[]T](collection Slice, fn func(item T, index int) T) { + for i := range collection { + collection[i] = fn(collection[i], i) + } +} + // Shuffle returns an array of shuffled values. Uses the Fisher-Yates shuffle algorithm. -// Play: https://go.dev/play/p/ZTGG7OUCdnp +// Play: https://go.dev/play/p/2xb3WdLjeSJ func Shuffle[T any, Slice ~[]T](collection Slice) { rand.Shuffle(len(collection), func(i, j int) { collection[i], collection[j] = collection[j], collection[i] @@ -11,7 +59,7 @@ func Shuffle[T any, Slice ~[]T](collection Slice) { } // Reverse reverses array so that the first element becomes the last, the second element becomes the second to last, and so on. -// Play: https://go.dev/play/p/iv2e9jslfBM +// Play: https://go.dev/play/p/O-M5pmCRgzV func Reverse[T any, Slice ~[]T](collection Slice) { length := len(collection) half := length / 2 diff --git a/vendor/github.com/samber/lo/slice.go b/vendor/github.com/samber/lo/slice.go index e03cba0..9c15a6c 100644 --- a/vendor/github.com/samber/lo/slice.go +++ b/vendor/github.com/samber/lo/slice.go @@ -38,8 +38,8 @@ func UniqMap[T any, R comparable](collection []T, iteratee func(item T, index in result := make([]R, 0, len(collection)) seen := make(map[R]struct{}, len(collection)) - for i, item := range collection { - r := iteratee(item, i) + for i := range collection { + r := iteratee(collection[i], i) if _, ok := seen[r]; !ok { result = append(result, r) seen[r] = struct{}{} @@ -55,7 +55,7 @@ func UniqMap[T any, R comparable](collection []T, iteratee func(item T, index in // // Play: https://go.dev/play/p/-AuYXfy7opz func FilterMap[T any, R any](collection []T, callback func(item T, index int) (R, bool)) []R { - result := []R{} + result := make([]R, 0, len(collection)) for i := range collection { if r, ok := callback(collection[i], i); ok { @@ -188,6 +188,19 @@ func GroupBy[T any, U comparable, Slice ~[]T](collection Slice, iteratee func(it return result } +// GroupByMap returns an object composed of keys generated from the results of running each element of collection through iteratee. +func GroupByMap[T any, K comparable, V any](collection []T, iteratee func(item T) (K, V)) map[K][]V { + result := map[K][]V{} + + for i := range collection { + k, v := iteratee(collection[i]) + + result[k] = append(result[k], v) + } + + return result +} + // Chunk returns an array of elements split into groups the length of size. If array can't be split evenly, // the final chunk will be the remaining elements. // Play: https://go.dev/play/p/EeKl0AuTehH @@ -408,8 +421,8 @@ func FilterSliceToMap[T any, K comparable, V any](collection []T, transform func func Keyify[T comparable, Slice ~[]T](collection Slice) map[T]struct{} { result := make(map[T]struct{}, len(collection)) - for _, item := range collection { - result[item] = struct{}{} + for i := range collection { + result[collection[i]] = struct{}{} } return result diff --git a/vendor/github.com/samber/lo/string.go b/vendor/github.com/samber/lo/string.go index 51b0989..6a10955 100644 --- a/vendor/github.com/samber/lo/string.go +++ b/vendor/github.com/samber/lo/string.go @@ -1,13 +1,14 @@ package lo import ( - "github.com/samber/lo/internal/rand" "math" "regexp" "strings" "unicode" "unicode/utf8" + "github.com/samber/lo/internal/rand" + "golang.org/x/text/cases" "golang.org/x/text/language" ) @@ -108,7 +109,7 @@ func Substring[T ~string](str T, offset int, length uint) T { length = uint(size - offset) } - return T(strings.Replace(string(rs[offset:offset+int(length)]), "\x00", "", -1)) + return T(strings.ReplaceAll(string(rs[offset:offset+int(length)]), "\x00", "")) } // ChunkString returns an array of strings split into groups the length of size. If array can't be split evenly, diff --git a/vendor/modules.txt b/vendor/modules.txt index 35ab597..a4ab065 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -14,7 +14,7 @@ github.com/google/go-cmp/cmp/internal/value # github.com/pmezard/go-difflib v1.0.0 ## explicit github.com/pmezard/go-difflib/difflib -# github.com/samber/lo v1.49.1 +# github.com/samber/lo v1.50.0 ## explicit; go 1.18 github.com/samber/lo github.com/samber/lo/internal/constraints