【问题标题】:go type conversion - sort 2 slices of different interfaces using shared interfacego type conversion - 使用共享接口对不同接口的 2 片进行排序
【发布时间】:2018-08-26 18:27:52
【问题描述】:

下面的示例包含两个接口FooBar,它们都实现了相同的接口Timestamper。它还包含实现sort.Interface 的类型ByTimestamp

如函数main 所示,我想使用ByTimestamp 类型对Foos 的切片和Bars 的切片进行排序。但是,代码不会编译,因为它有cannot convert foos (type []Foo) to type ByTimestampcannot convert bars (type []Bar) to type ByTimestamp

是否可以对实现相同接口的 2 个不同接口切片与实现 sort.Interface 的单一类型进行排序?

package main

import (
    "sort"
)

type Timestamper interface {
    Timestamp() int64
}

type ByTimestamp []Timestamper

func (b ByTimestamp) Len() int {
    return len(b)
}

func (b ByTimestamp) Swap(i, j int) {
    b[i], b[j] = b[j], b[i]
}

func (b ByTimestamp) Less(i, j int) bool {
    return b[i].Timestamp() < b[j].Timestamp()
}

type Foo interface {
    Timestamper
    DoFoo() error
}

type Bar interface {
    Timestamper
    DoBar() error
}

func getFoos() (foos []Foo) {
    // TODO get foos
    return
}

func getBars() (bars []Bar) {
    // TODO get bars
    return
}

func main() {
    foos := getFoos()
    bars := getBars()

    sort.Sort(ByTimestamp(foos))
    sort.Sort(ByTimestamp(bars))
}

The Go playground

【问题讨论】:

  • 它必须是sort.Interface的实现吗?带有类型断言的 sort.Slice 应该可以工作。

标签: sorting go type-conversion


【解决方案1】:

是的,可以使用一个sort.Interface 对不同类型进行排序。 但不是你试图这样做的方式。当前的 Go 规范不允许将一种切片类型转换为另一种。您必须转换每个项目。

这是一个使用反射的辅助函数:

// ByTimestamp converts a slice of Timestamper into a slice
// that can be sorted by timestamp.
func ByTimestamp(slice interface{}) sort.Interface {
    value := reflect.ValueOf(slice)
    length := value.Len()
    b := make(byTimestamp, 0, length)
    for i := 0; i < length; i++ {
        b = append(b, value.Index(i).Interface().(Timestamper))
    }
    return b
}

查看完整示例here

而且,如果您只有几种类型,那么进行特定于类型的转换可能是有意义的。

【讨论】:

    猜你喜欢
    • 2017-08-29
    • 2020-11-29
    • 2013-04-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-19
    • 2020-05-17
    • 1970-01-01
    相关资源
    最近更新 更多