93 lines
2.4 KiB
Go
93 lines
2.4 KiB
Go
package gu
|
|
|
|
import "fmt"
|
|
|
|
// InterfaceSlice transforms a slice of any type to a slice of interface{}.
|
|
// This can be usefull when you have a slice of concrete types that has to be passed
|
|
// to a function that takes a (variadic) slice of interface{}.
|
|
func InterfaceSlice[T any](slice []T) []interface{} {
|
|
out := make([]interface{}, len(slice))
|
|
|
|
for i := 0; i < len(slice); i++ {
|
|
out[i] = slice[i]
|
|
}
|
|
|
|
return out
|
|
}
|
|
|
|
// AssertInterfaces asserts all members of the passed slice of interfaces
|
|
// to the requested type and returs a slice of that type.
|
|
// A nil slice allong with an error is returned
|
|
// if one of the entries cannot be asserted to the destination type.
|
|
func AssertInterfaces[T any](is []interface{}) ([]T, error) {
|
|
out := make([]T, len(is))
|
|
|
|
for i := 0; i < len(is); i++ {
|
|
var ok bool
|
|
|
|
if out[i], ok = is[i].(T); !ok {
|
|
return nil, fmt.Errorf("cannot assert %T of value %v to %T at index %d", is[i], is[i], out[i], i)
|
|
}
|
|
}
|
|
|
|
return out, nil
|
|
}
|
|
|
|
// AssertInterfacesP is like AssertInterfaces, only that it does not
|
|
// check for succesfull assertion and lets the runtime panic if assertion fails.
|
|
// Usefull for inlining in cases where you are 100% sure of the concrete type of the passed slice.
|
|
func AssertInterfacesP[T any](is []interface{}) []T {
|
|
out := make([]T, len(is))
|
|
|
|
for i := 0; i < len(is); i++ {
|
|
out[i] = is[i].(T)
|
|
}
|
|
|
|
return out
|
|
}
|
|
|
|
// Transform a slice of type 'A' to a slice of type 'B',
|
|
// by calling transFunc for each entry.
|
|
//
|
|
// Usefull when working with slices of different, but similar,
|
|
// struct types and you don't want to write the 'for' loops
|
|
// over and over again.
|
|
func Transform[A any, B any](as []A, transFunc func(A) B) []B {
|
|
if as == nil {
|
|
return nil
|
|
}
|
|
|
|
out := make([]B, len(as))
|
|
|
|
for i, a := range as {
|
|
out[i] = transFunc(a)
|
|
}
|
|
|
|
return out
|
|
}
|
|
|
|
// TransformErr is similar to Transform,
|
|
// but it uses a transFunc that can return an error.
|
|
//
|
|
// TranformErr will fail on the first error returned
|
|
// and returns a wrapped error with index information,
|
|
// along with a partial slice from previous succesfull operations.
|
|
func TransformErr[A any, B any](as []A, transFunc func(A) (B, error)) ([]B, error) {
|
|
if as == nil {
|
|
return nil, nil
|
|
}
|
|
|
|
out := make([]B, 0, len(as))
|
|
|
|
for i, a := range as {
|
|
b, err := transFunc(a)
|
|
if err != nil {
|
|
return out, fmt.Errorf("transform index %d: %w", i, err)
|
|
}
|
|
|
|
out = append(out, b)
|
|
}
|
|
|
|
return out, nil
|
|
}
|