EdgexAgent/device-gps-go/vendor/github.com/muhlemmer/gu/slice.go
2025-07-10 20:30:06 +08:00

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
}