按通过原型消息定义的日期对 GO 结构进行排序

sorting a GO struct by date which is defined via proto message

我在原型文件中定义了一条消息:

my.proto
--------
message Holiday {
  string title = 1;
  google.protobuf.Timestamp date = 2;
}

编译后创建my.pb.go

现在在我的 go 代码中,我有一段假期。

main.go
-------
holidays := []my.Holiday{...}

我必须按 Holiday.date 对这个切片进行排序。根据文档,如果我想使用 sort.Sort 进行排序,那么我必须实现 Len、Swap & Less 方法。但是我不能在我的 go 代码中定义这些接收器方法,因为 Holiday 来自不同的包 (my.pb.go)。 有什么办法可以解决这个问题吗?

谢谢,

您可以只使用 sort.Slice,不需要实施 sort.Interface

Slice sorts the slice x given the provided less function. It panics if x is not a slice.

sort.Slice(holidays, func(i, j int) bool {
    return holidays[i].GetDate().Before(holidays[j].GetDate())  
})

SortKeys 示例 in the sort.Sort documentation 显示了如何使用临时结构来完成此操作:

// A Planet defines the properties of a solar system object.
type Planet struct {
    name     string
    mass     earthMass
    distance au
}

// By is the type of a "less" function that defines the ordering of its Planet arguments.
type By func(p1, p2 *Planet) bool

// Sort is a method on the function type, By, that sorts the argument slice according to the function.
func (by By) Sort(planets []Planet) {
    ps := &planetSorter{
        planets: planets,
        by:      by, // The Sort method's receiver is the function (closure) that defines the sort order.
    }
    sort.Sort(ps)
}

// planetSorter joins a By function and a slice of Planets to be sorted.
type planetSorter struct {
    planets []Planet
    by      func(p1, p2 *Planet) bool // Closure used in the Less method.
}

// Len is part of sort.Interface.
func (s *planetSorter) Len() int {
    return len(s.planets)
}

// Swap is part of sort.Interface.
func (s *planetSorter) Swap(i, j int) {
    s.planets[i], s.planets[j] = s.planets[j], s.planets[i]
}

// Less is part of sort.Interface. It is implemented by calling the "by" closure in the sorter.
func (s *planetSorter) Less(i, j int) bool {
    return s.by(&s.planets[i], &s.planets[j])
}

鉴于 sort.Sort 只需要一个 sort.Interface,它不关心你使用的是什么数据结构或者你实际交换的是什么类型。

sort package documentation 显示了回答问题的两个示例。

first package example 使用所需方法声明切片类型:

type Person struct {
    Name string
    Age  int
}

type ByAge []Person

func (a ByAge) Len() int           { return len(a) }
func (a ByAge) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }
func (a ByAge) Less(i, j int) bool { return a[i].Age < a[j].Age }

...
sort.Sort(ByAge(people))

请注意,Len、Swap 和 Less 方法是在为排序定义的切片类型上,而不是在结构类型上。您可以在自己的包中定义该类型。

sort.Slice example 显示了如何仅使用 less 函数进行排序:

sort.Slice(people, func(i, j int) bool { return people[i].Name < people[j].Name })

在此示例中,无需为排序目的定义类型。