首页 > 解决方案 > 如何实现通用过滤器功能?

问题描述

假设我正在实现这个函数来过滤 Golang 中的切片:

 func Filter(filter func(n int) bool) func(list []int) []int {
   return func(list []int) []int {
     r := make([]int, 0)
     for _, n := range list {
         if filter(n) {
             r = append(r, n)
         }
   }

     return r
 } 
}

像这样使用:

list := []int{1, 4, 3, 2, 7, 4, 9, 7}
r := Filter(func(n int) bool { return n > 3 })(list)

fmt.Println(r)

这工作正常,但我有以下问题:

  1. 我应该使用完整的 func 语法而不是 lambda 样式表达式吗?
  2. 如果我希望我的过滤器过滤任何类型的切片,我应该使用什么返回类型?

谢谢!

标签: gogenericshigher-order-functions

解决方案


  1. 据我所知,尚未接受更简洁的匿名函数表示法(“lambda”)的提议。

  2. 随着 Go 1.18 的发布,计划在 2022 年初向该语言添加类型参数(又名泛型)。然后,您将能够编写下面的程序(操场)。

    如果你能等到那个时候,那就去做吧。无论如何,通常不鼓励使用reflect在代码中添加空interface{}断言和类型断言。在 Go 1.18 之前,一种可行的替代方案是用于go generate生成您需要的不同专业化(for intstring等)。

    package main
    
    import "fmt"
    
    func Filter[T any](filter func(n T) bool) func(T []T) []T {
        return func(list []T) []T {
            r := make([]T, 0, len(list))
            for _, n := range list {
                if filter(n) {
                    r = append(r, n)
                }
            }
            return r
        }
    }
    
    func main() {
        list := []int{1, 4, 3, 2, 7, 4, 9, 7}
        r := Filter(func(n int) bool { return n > 3 })(list)
        fmt.Println(r)
    
        list2 := []string{"foo", "bar", "baz", "qux", "quux"}
        r2 := Filter(func(s string) bool { return len(s) <= 3 })(list2)
        fmt.Println(r2)
    }
    

推荐阅读