作者:mobiledu2502913567 | 来源:互联网 | 2023-10-11 17:12
我有多个带有“DateLastModified”字段的结构,如下所示:
type Thing struct {
DateLastModified time.Time
...
}
type Thing2 struct {
DateLastModified time.Time
...
}
我有每个这些结构的切片或映射:
things := []Thing{...}
thing2s := []Thing2{...}
//or
things := make(map[string]Thing)
thing2s := make(map[string]Thing2)
我想要做的是过滤他们DateLastModified
领域中的每个切片或地图。
这很容易以基本方式实现,但我有兴趣了解更多关于 Go 的知识。
我想知道的是:有没有办法以我可以执行以下操作的方式实现该过滤器:
filteredThings := filterSliceOnTime(things, someTimeToFilterOn)
filtered2Things := filterSliceOnTime(thing2s, someTimeToFilterOn)
//or
filteredThings := filterMapOnTime(things, someTimeToFilterOn)
filtered2Things := filterMapOnTime(thing2s, someTimeToFilterOn)
我想弄清楚的是如何减少冗余代码,因为所有这些结构都具有 DateLastModified 字段。
谢谢!
回答
Go 没有协方差的概念,因此filterXOnTime
将无法对不同底层结构的切片[]V
或映射进行操作。map[K]V
V
带接口
您可以做的是声明一个I
公开公共行为的接口,并让两个结构都实现该接口:
type Modifiable interface {
GetDateLastModified() time.Time
}
type Thing struct {
DateLastModified time.Time
...
}
func (t Thing) GetDateLastModified() time.Time {
return t.DateLastModified
}
type Thing2 struct {
DateLastModified time.Time
...
}
func (t Thing2) GetDateLastModified() time.Time {
return t.DateLastModified
}
此时,您可以拥有 的切片和映射I
,并且您的过滤器功能可以与这些一起工作(接受和返回):
func filterSliceOnTime(modifiables []Modifiable, someTimeToFilterOn time.Time) []Modifiable {
var filtered []Modifiable
for _, m := range modifiables {
if m.GetDateLastModified.After(someTimeToFilterOn) {
filtered = append(filtered, m)
}
}
return filtered
}
这种方法的有效性受到以下事实的限制:为了使用“通用”函数,您必须重新映射[]ThingX
到[]Modifiable
,反之亦然。
带有辅助函数
为了减轻上述解决方案的维护麻烦,您可以改用一个对单个项目进行操作的辅助过滤器功能,这样您就不必来回映射复杂类型:
func checkOne(v Modifiable, filterOn time.Time) bool {
return v.GetDateLastModified().After(filterOn)
}
func main() {
a := make(map[string]Thing, 0)
a["foo"] = Thing{time.Now()}
filtered := make(map[string]Thing, 0)
for k, v := range a {
if checkOne(v, time.Now().Add(-2*time.Hour)) {
filtered[k] = v
}
} fmt.Println(filtered) // map[foo:{blah}]
}
Go 1.18 并输入参数
随着 Go 1.18(2022 年初)和泛型的引入,您将能够直接使用切片和映射。您仍然需要声明接口来为类型参数提供适当的约束,并且结构仍然必须实现它。
使用当前的草稿设计,可能看起来像:
func filterSliceOnTime[T Modifiable](s []T, filterOn time.Time) []T {
var filtered []T
for _, v := range s {
if v.GetDateLastModified().After(filterOn) {
filtered = append(filtered, v)
}
}
return filtered
}
Go2 游乐场:https ://go2goplay.golang.org/p/FELhv0NSr5A