go-linq按照时间排序
Posted lishuangquan1987
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了go-linq按照时间排序相关的知识,希望对你有一定的参考价值。
写惯了C#的linq,对集合进行各种操作,很丝滑,突然写go的时候,操作slice不知所措。
于是在github上找到了这个库:https://github.com/ahmetb/go-linq,又回到了丝滑的感觉。
但是在按照时间排序的时候,报错了。
先上代码:
package main
import (
"fmt"
"time"
"github.com/ahmetb/go-linq/v3"
)
func main()
list := make([]Person, 0)
list = append(list,
Person
Name: "tony1",
Age: 1,
Born: time.Date(2000, 1, 1, 8, 0, 0, 0, time.Local),
, Person
Name: "tony2",
Age: 1,
Born: time.Date(2001, 1, 1, 8, 0, 0, 0, time.Local),
,
Person
Name: "tony3",
Age: 1,
Born: time.Date(2002, 1, 1, 8, 0, 0, 0, time.Local),
)
orderedList := make([]Person, 0)
linq.From(list).OrderByDescending(func(i interface) interface return i.(Person).Born ).ToSlice(&orderedList)
fmt.Println(orderedList)
type Person struct
Name string
Age int
Born time.Time
运行报如下错误:
panic: interface conversion: time.Time is not linq.Comparable: missing method CompareTo
说的是time.Time不是linq.Comparable。
查看linq.Comparable,发现定义如下:
// Comparable is an interface that has to be implemented by a custom collection
// elements in order to work with linq.
//
// Example:
// func (f foo) CompareTo(c Comparable) int
// a, b := f.f1, c.(foo).f1
//
// if a < b
// return -1
// else if a > b
// return 1
//
//
// return 0
//
type Comparable interface
CompareTo(Comparable) int
连同注释一起复制过来了,意思是要实现比较,就必须让类型实现Comparable 接口。
那么如何让time.Time
实现linq.Comparable
接口呢?
错误的尝试:
这还不简单,直接写一个time.Time的对象方法,这样time.Time不就自动实现了linq.Comparable接口了
func (a time.Time) CompareTo(c linq.Comparable) int
b := c.(time.Time)
if a.After(b)
return 1
else if a.Equal(b)
return 0
else
return -1
But,当写完这个方法之后,发现报错了!!!
意思是,time.Time没有在main包中定义,原来go只允许拓展struct所在包的方法
正确的方式
既然time.Time没有定义在main包,那我们自己定义一种类型,在自己的类型上实现linq.Comparable
这个方法,而我们自定义的类型,与time.Time肯定有着千丝万缕的关系。
C#的面向对象思想:组合优于继承
那就用组合的方式,将time.Time包装到自定义类型的里面,更改后的代码如下:
方式一
package main
import (
"fmt"
"time"
"github.com/ahmetb/go-linq/v3"
)
func main()
list := make([]Person, 0)
list = append(list,
Person
Name: "tony1",
Age: 1,
Born: time.Date(2000, 1, 1, 8, 0, 0, 0, time.Local),
, Person
Name: "tony2",
Age: 1,
Born: time.Date(2001, 1, 1, 8, 0, 0, 0, time.Local),
,
Person
Name: "tony3",
Age: 1,
Born: time.Date(2002, 1, 1, 8, 0, 0, 0, time.Local),
)
orderedList := make([]Person, 0)
linq.From(list).OrderByDescending(func(i interface) interface return NewMytime(i.(Person).Born) ).ToSlice(&orderedList)
fmt.Println(orderedList)
type Person struct
Name string
Age int
Born time.Time
type Mytime struct
Time time.Time
func NewMytime(t time.Time) Mytime
return MytimeTime: t
func (a Mytime) CompareTo(c linq.Comparable) int
b := c.(Mytime)
if a.Time.After(b.Time)
return 1
else if a.Time.Equal(b.Time)
return 0
else
return -1
方式二
package main
import (
"fmt"
"time"
"github.com/ahmetb/go-linq/v3"
)
func main()
list := make([]Person, 0)
list = append(list,
Person
Name: "tony1",
Age: 1,
Born: NewMytime(time.Date(2000, 1, 1, 8, 0, 0, 0, time.Local)),
, Person
Name: "tony2",
Age: 1,
Born: NewMytime(time.Date(2001, 1, 1, 8, 0, 0, 0, time.Local)),
,
Person
Name: "tony3",
Age: 1,
Born: NewMytime(time.Date(2002, 1, 1, 8, 0, 0, 0, time.Local)),
)
orderedList := make([]Person, 0)
linq.From(list).OrderByDescending(func(i interface) interface return i.(Person).Born ).ToSlice(&orderedList)
fmt.Println(orderedList)
type Person struct
Name string
Age int
Born Mytime
type Mytime struct
Time time.Time
func NewMytime(t time.Time) Mytime
return MytimeTime: t
func (a Mytime) CompareTo(c linq.Comparable) int
b := c.(Mytime)
if a.Time.After(b.Time)
return 1
else if a.Time.Equal(b.Time)
return 0
else
return -1
最后运行,结果跟预期的一致:
以上两种方式,都是定义一个Mytime
将time.Time
聚合在里面。
但是反问自己,真的不能用继承的方式吗???
于是有了第三种方式的解法:
方式三
先定义一个time.Time的类型叫CustomTime
,并实现linq.Comparable
接口
type CustomTime time.Time
func (a CustomTime) CompareTo(c linq.Comparable) int
aa := time.Time(a)
bb := time.Time(c.(CustomTime))
if aa.After(bb)
return 1
else if aa.Equal(bb)
return 0
else
return -1
排序的时候,强制转换为CustomTime
类型:
func main()
list := make([]Person, 0)
list = append(list,
Person
Name: "tony1",
Age: 1,
Born: time.Date(2000, 1, 1, 8, 0, 0, 0, time.Local),
, Person
Name: "tony2",
Age: 1,
Born: time.Date(2001, 1, 1, 8, 0, 0, 0, time.Local),
,
Person
Name: "tony3",
Age: 1,
Born: time.Date(2002, 1, 1, 8, 0, 0, 0, time.Local),
)
orderedList := make([]Person, 0)
linq.From(list).OrderByDescending(func(i interface) interface return CustomTime(i.(Person).Born) ).ToSlice(&orderedList)
fmt.Println(orderedList)
return CustomTime(i.(Person).Born)
这里就是将time.Time
强制转换为CustomTime
因为它们是同一个类型
以后遇到要拓展第三方包或者系统struct的类型时,就推荐使用第三种方式
以上是关于go-linq按照时间排序的主要内容,如果未能解决你的问题,请参考以下文章