删除切片指定元素,Go 标准库并未给出相应的函数,需要我们自己实现。以 []int 类型的切片为例,我们可能会直接写出下面的函数。
func DeleteSliceElms(sl []int, elms ...int) []int {
if len(sl) == 0 || len(elms) == 0 {
return sl
}
m := make(map[int]struct{})
for _, v := range elms {
m[v] = struct{}{}
}
res := make([]int, 0, len(sl))
for _, v := range sl {
if _, ok := m[v]; !ok {
res = append(res, v)
}
}
return res
}
sl := []int{1, 2, 3, 3, 2, 5}
res := DeleteSliceElms(sl, 2, 3)
完全没有问题,上面的函数完美了实现了我们想要的功能。
但是如果我们现在又需要对 []string 类型的切片删除指定的元素,你可能想到的是拷贝一下上面的函数,改下对应的类型即可。
func DeleteStrSliceElms(sl []string, elms ...string) []string {
if len(sl) == 0 || len(elms) == 0 {
return sl
}
m := make(map[string]struct{})
for _, v := range elms {
m[v] = struct{}{}
}
res := make([]string, 0, len(sl))
for _, v := range sl {
if _, ok := m[v]; !ok {
res = append(res, v)
}
}
return res
}
如此又解决了我们的问题。但是如果我们又需要对其他类型的切片进行删除,难道故技重施,再次拷贝重复的代码吗?
面对重复的代码,我们应该消灭它,而不是助长它。如何消灭呢,这本该是泛型要做的事情,可惜在 Go(截止 Go 1.17)不支持范型。但是 Go 为我们提供了反射,我们可以利用反射,间接地实现范型的效果:只写一个函数,支持所有类型的切片。
参考文献
|