定义一种具有比较能力的类型是一种常见需求,比如对一组相同类型的值进行排序,就需要进行两两比较,那么在Go语言中有没有办法定义一种具有比较能力的Interface,实现该接口的类型都具备比较能力呢,最常见最容易的办法是定义一个与 any
比较的接口方法:
type Comparable interface {
func LessThen(a any) bool
}
func Sort[T Comparable] (s []T) {
// s[i].LessThen(s[j])
}
具体实现的时候进行类型断言:
type User struct {
Age int
}
func(u *User) LessThen(a any) bool {
u2, ok := a.(*User)
if !ok {
return false
}
return u.Age < u2.Age
}
多少缺点意思,没办法约束比较目标的类型与自己相同,于是我们想到可以利用 Go1.18 引入的范型来约束比较目标类型,于是 Comparable
定义改进为:
type Comparable[T any] interface {
func LessThen(t T) bool
}
实现改变为:
// 实现接口 Comparable[*User]
func(u *User) LessThen(u2 *User) bool {
return u.Age < u2.Age
}
随之 Sort
方法也要修改:
func Sort[T Comparable[*User]] (s []T) {
// s[i].LessThen(s[j])
}
但这样的 Sort
方法限制了 T
只能与 *User
比较,要想 T
具有与自身类型比较的能力,Sort
定义需要再次修改:
func Sort[T Comparable[T]] (s []T) {
// s[i].LessThen(s[j])
}
这样的 Sort
方法定义就比较通用了,基本实现了我们最初的目标,虽然看起来有点晦涩难懂,但好在接口实现比较简单, 比如:
type Int int
func (i Int) LessThen(o Int) bool {
return i < o
}
Sort([]Int{3, 5, 7})
type Time time.Time
func (t Time) LessThen(t2 Time) bool {
return time.Time(t).Before(time.Time(o))
}
Sort([]Time{Time(time.Now()), Time(time.Now().Add(-time.Minute))})
期待后面版本的 Go 语言的 Interface
和范型加入对 self
的支持,这样的话我们的接口定义就会变得简单直接,比如:
// 伪代码,无法编译
// 限制它的实现必须是与实现者自身类型比较,而不是其他类型
type Comparable interface {
func LessThen(t self) bool
}
Golang 2 目前有一个提案就是讨论关于 self
的: https://github.com/golang/go/issues/28254,有兴趣也可以关注参与