diff --git a/sliceutil/sliceutil.go b/sliceutil/sliceutil.go index 3d44279..1ce305a 100644 --- a/sliceutil/sliceutil.go +++ b/sliceutil/sliceutil.go @@ -8,6 +8,7 @@ package sliceutil // import "github.com/teamwork/utils/sliceutil" import ( "math/rand" + "reflect" "sort" "strconv" "strings" @@ -214,3 +215,24 @@ func StringMap(list []string, f func(string) string) []string { return ret } + +// InterfaceSliceTo converts []interface to any given slice. +// It will ~optimistically~ try to convert interface item to the dst item type +func InterfaceSliceTo(src []interface{}, dst interface{}) interface{} { + dstt := reflect.TypeOf(dst) + if dstt.Kind() != reflect.Slice { + panic("`dst` is not an slice") + } + + dstV := reflect.ValueOf(dst) + + for i := range src { + if i < dstV.Len() { + dstV.Index(i).Set(reflect.ValueOf(src[i]).Convert(dstt.Elem())) + continue + } + dstV = reflect.Append(dstV, reflect.ValueOf(src[i]).Convert(dstt.Elem())) + } + + return dstV.Interface() +} diff --git a/sliceutil/sliceutil_test.go b/sliceutil/sliceutil_test.go index e4d07c1..e0c5a15 100644 --- a/sliceutil/sliceutil_test.go +++ b/sliceutil/sliceutil_test.go @@ -528,3 +528,49 @@ func TestStringMap(t *testing.T) { }) } } + +func TestInterfaceSliceTo(t *testing.T) { + { + src := []interface{}{"1", "2", "3", "4", "5"} + want := []string{"1", "2", "3", "4", "5"} + input := []string{""} + + result := InterfaceSliceTo(src, input) + if !reflect.DeepEqual(result, want) { + t.Fatalf("want %+v(%T),\tgot %+v(%T)", want, want, result, result) + } + } + + { + src := []interface{}{"1", "2", "3", "4", "5"} + want := []string{"1", "2", "3", "4", "5"} + input := []string{} + + result := InterfaceSliceTo(src, input) + if !reflect.DeepEqual(result, want) { + t.Fatalf("want %+v(%T),\tgot %+v(%T)", want, want, result, result) + } + } + + { + src := []interface{}{1, 2, 3, 4, 5} + want := []int{1, 2, 3, 4, 5} + input := []int{0, 0} + + result := InterfaceSliceTo(src, input) + if !reflect.DeepEqual(result, want) { + t.Fatalf("want %+v(%T),\tgot %+v(%T)", want, want, result, result) + } + } + + { + src := []interface{}{1, 2, 3, 4, 5} + want := []int64{1, 2, 3, 4, 5} + input := []int64{0, 0} + + result := InterfaceSliceTo(src, input) + if !reflect.DeepEqual(result, want) { + t.Fatalf("want %+v(%T),\tgot %+v(%T)", want, want, result, result) + } + } +}