I want to make a method that accepts different data typs, but Go has no generics. I have to write the following duplicate code:
func GetRandomSubarrayInt64(candidates []int64, length int) []int64 {
result := make([]int64, 0, length)
if len(candidates) == 0 {
return result
}
if len(candidates) <= length {
return candidates
}
rand.Shuffle(len(candidates), func(i, j int) {
candidates[i], candidates[j] = candidates[j], candidates[i]
})
return candidates[:length]
}
func GetRandomSubarrayString(candidates []string, length int) []string {
result := make([]string, 0, length)
if len(candidates) == 0 {
return result
}
if len(candidates) <= length {
return candidates
}
rand.Shuffle(len(candidates), func(i, j int) {
candidates[i], candidates[j] = candidates[j], candidates[i]
})
return candidates[:length]
}
The code is almost repetitive.Is there a way to reduce duplicate code?
Yes, Golang not support Generics right now.
But you can try this way:
func GetRandomSubarray(candidates interface{}, length int) interface{} {
candidatesValue := reflect.ValueOf(candidates)
if candidatesValue.Kind() != reflect.Slice {
panic("supports slice only")
}
if candidatesValue.Len() == 0 {
return candidates
}
if candidatesValue.Len() <= length {
return candidates
}
rand.Shuffle(candidatesValue.Len(), reflect.Swapper(candidates))
return candidatesValue.Slice(0, length).Interface()
}
Usage:
s := []string{"1", "2", "3"}
rs := GetRandomSubarray(s, 1).([]string)
i := []int{1, 2, 3}
ri := GetRandomSubarray(i, 1).([]int)
You can define a interface that exports methods to swap items in a generic underlying array. Then you will need to implement this interface with your type-specific array/slice. Something like this.
type ShuffleSlice interface {
Swap(i, j int)
Len() int
}
func GetRandomSubslice(candidates ShuffleSlice) ShuffleSlice {
if candidates == nil || candidates.Len() == 0 {
return nil
}
rand.Shuffle(candidates.Len(), func(i, j int) {
candidates.Swap(i, j)
})
return candidates
}
type ShuffleSliceInt []int
func (s ShuffleSliceInt) Swap(i, j int) {
s[i], s[j] = s[j], s[i]
}
func (s ShuffleSliceInt) Len() int {
return len(s)
}