Go 泛型 filter 功能实现
功能实现:过滤一下切片中符合条件的元素,并返回
正常情况下的话土拨鼠会简单写一下,一般都是作为一次性使用。
简单版
// filter 过滤掉不符合条件的元素
func filter(items []interface{}) []interface{} {
filteredItems := []interface{}{}
for index, value := range items {
// 过滤掉奇数
if num.(int)%2 == 0 {
filteredItems = append(filteredItems, value)
}
}
return filteredItems
}
显然这样写太简单了,一点都不够优雅。条件函数的话这里可以考虑用闭包作为函数参数来稍微优化一下。这样就可以编写各种花样的过滤逻辑咯。
优化版
// filter 过滤掉不符合条件的元素
func filter(items []interface{}, fn func(index int, item interface{}) bool) []interface{} {
filteredItems := []interface{}{}
for index, value := range items {
if fn(index, value) {
filteredItems = append(filteredItems, value)
}
}
return filteredItems
}
func main() {
var nums []interface{}
nums = append(nums, 1, 2, 3, 4, 5)
evenNums := filter(nums, func(index int, num interface{}) bool { return num.(int)%2 == 0 })
fmt.Printf("%d", evenNums[0].(int) + 2)
}
约束版
为了使得类型使用更加清晰明了一些,咱们这里使用any
类型(可不是随便起的哦,可以参考类型参数提案中any的约束[3])来替代interface{}
类型。修改如下:
type any = interface{}
// filter 过滤掉不符合条件的元素
func filter(items []any, fn func(index int, item any) bool) []any {
filteredItems := []any{}
for index, value := range items {
if fn(index, value) {
filteredItems = append(filteredItems, value)
}
}
return filteredItems
}
这里给大家讲一下什么是约束?约束主要是确保泛型类型的元素始终满足特定的接口类型。根据 Go 的哲学,必须在类型参数声明旁边添加约束。这个demo使用的是any
类型等同于interface{}
,可以接受任意类型的。所以这里的约束作用就由闭包来做了。
func filter[T SomeInterface](items []T )
大家也可以在go2goPlayground[4]进行测试,最终demo如下:
package main
import (
"fmt"
)
// filter 过滤掉不符合条件的元素
func filter[T any](items []T, fn func(item T "T any") bool) []T {
filteredItems := []T{}
for _, value := range items {
if fn(value) {
filteredItems = append(filteredItems, value)
}
}
return filteredItems
}
func main() {
nums := []int{1, 2, 3, 4, 5}
evenNums := filter(nums, func(num int) bool { return num%2 == 0 })
fmt.Println(evenNums)
}
参考资料
Go泛型系列:提前掌握Go泛型的基本使用: https://polarisxu.studygolang.com/posts/go/generics/generics-basic
[2]Implementing a Generic Filter Function in Go: https://preslav.me/2021/09/22/implementing-a-generic-filter-function-in-golang/
[3]类型参数提案中any的约束: https://go.googlesource.com/proposal/+/refs/heads/master/design/43651-type-parameters.md#the-constraint
[4]go2goPlayground: https://go2goplay.golang.org/
[5]go: don't change the libraries in 1.18: https://github.com/golang/go/issues/48918
[6]#45955-slices: new package to provide generic slice functions: https://github.com/golang/go/issues/45955
[7]#48594-proposal: bytes: add Grow, Clip; maybe add bytes/strings Insert, Delete: https://github.com/golang/go/issues/48594
推荐阅读