You can use some functions of package
reflect
to make this code generic, the main one is this.
func Swapper(slice interface{}) func(i, j int)
Swapper Returns a Function that swaps the Elements in the provided
Slice.
Swapper panics if the provided interface is not a Slice.
It returns another function which is a changer to the Slice, that does the same thing as this line in your code:
(*ptr)[i], (*ptr)[j] = (*ptr)[j], (*ptr)[i]
Example using these features:
type AnySlice interface{}
func Shuffle(slice AnySlice, seed int64) {
rv := reflect.ValueOf(slice)
swapper := reflect.Swapper(rv.Interface())
rand.Seed(seed)
rand.Shuffle(rv.Len(), func(i, j int) {
swapper(i, j)
})
}
Call example:
intValues := []int{1, 2, 3, 4, 5}
strValues := []string{"a", "b", "c", "d", "e"}
seed := time.Now().UnixNano()
Shuffle(intValues, seed)
Shuffle(strValues, seed)
fmt.Printf("%#v\n%#v", intValues, strValues)
Like Slices are already "pointers", the use of &
and *
is unnecessary in this case.
PS: The Slices are already "pointers by default", they are passed as a reference and are not copied, so I don’t think I have a reason to return them as a result of the function (nor to use
*[]int
as input. But, this is another topic.– Inkeliz
Perhaps you could also use the
reflect.SliceHeader
with theunsafe
, but I don’t know if it’s worth it.– Inkeliz
Is there a difference in performance if using pointers? For me it is easier to read and understand
Shuffle(&slice, seed)
thanShuffle(slice, seed)
– x8ss