Go 泛型 filter 功能實現(xiàn)
功能實現(xiàn):過濾一下切片中符合條件的元素,并返回
正常情況下的話土撥鼠會簡單寫一下,一般都是作為一次性使用。
簡單版
//?filter?過濾掉不符合條件的元素
func?filter(items?[]interface{})?[]interface{}?{
????filteredItems?:=?[]interface{}{}
????for?index,?value?:=?range?items?{
????????//?過濾掉奇數(shù)
????????if?num.(int)%2?==?0?{
????????????filteredItems?=?append(filteredItems,?value)
????????}
????}
????return?filteredItems
}
顯然這樣寫太簡單了,一點都不夠優(yōu)雅。條件函數(shù)的話這里可以考慮用閉包作為函數(shù)參數(shù)來稍微優(yōu)化一下。這樣就可以編寫各種花樣的過濾邏輯咯。
優(yōu)化版
//?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類型(可不是隨便起的哦,可以參考類型參數(shù)提案中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
}
這里給大家講一下什么是約束?約束主要是確保泛型類型的元素始終滿足特定的接口類型。根據(jù) Go 的哲學,必須在類型參數(shù)聲明旁邊添加約束。這個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]類型參數(shù)提案中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
推薦閱讀
