到目前为止,在 Go 中创建函数 filter() 是很困难的,它可以根据谓词的布尔值来过滤任何元素的列表。如果你知道列表的类型,这是有可能的。
func filter(slice []string, f func(string) bool) []string { var n []string for _, e := range slice { if f(e) { n = append(n, e) } } return n }
|
这种解决方案的主要缺点是,你必须为每个slice类型写一个单独的函数,或者使用interface{}和类型断言。
然而,随着Go 1.18中泛型技术的发布,我们有能力编写类型为参数的函数。
所以现在写一个filter()函数来操作任何类型的slice是没有问题的。
package main
import ( "fmt" "strings" )
func filter[T any](slice []T, f func(T) bool) []T { var n []T for _, e := range slice { if f(e) { n = append(n, e) } } return n }
func main() { websites := []string{"http://foo.com", "https://bar.com", "https://gosamples.dev"} httpsWebsites := filter(websites, func(v string) bool { return strings.HasPrefix(v, "https://") }) fmt.Println(httpsWebsites)
numbers := []int{1, 2, 3, 4, 5, 6} divisibleBy2 := filter(numbers, func(v int) bool { return v % 2 == 0 }) fmt.Println(divisibleBy2) } 输出: [https://bar.com https://gosamples.dev] [2 4 6]
|
filter()函数接受一个T类型的slice作为参数。
T类型有any约束,这个约束意味着对slice的类型没有要求--它可以是任何东西。
同一类型的T被用作谓词函数的参数,该函数检查该值是否应该被添加到结果中。
filter()函数的主体很简单。它在slice上进行迭代,并将那些从谓词函数返回真值的元素添加到结果中。
正如你在这个例子的输出中所看到的,它对字符串和int类型的slice都有效,也可以对任何其他类型的slice有效。