一种处理不同数据类型的方法

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)
}