Golang排序接口切片

时间:2017-04-04 15:04:26

标签: go interface casting type-conversion

我在Golang中编写了一个CLI工具来包装API,我喜欢将它放在一起是多么简单。现在我想要使用另一个具有不同JSON结构的API来获取类似的值。我为结构创建了一个接口来实现,但我不太清楚Golang中的类型转换是如何工作的。

这是我放在一起的一个例子:

我有一个公共接口Vehicle,它暴露了一些方法

type Vehicle interface {
    Manufacturer() string
    Model() string
    Year() int
    Color() string
    String() string
}

我还想对实现此接口的所有结构进行排序,因此我添加了一个实现排序接口的Vehicle类型

type Vehicles []Vehicle

func (s Vehicles) Len() int {
    return len(s)
}

func (s Vehicles) Less(i, j int) bool {
    if s[i].Manufacturer() != s[j].Manufacturer() {
        return s[i].Manufacturer() < s[j].Manufacturer()
    } else {
        if s[i].Model() != s[j].Model() {
            return s[i].Model() < s[j].Model()
        } else {
            return s[i].Year() < s[j].Year()
        }
    }
}

func (s Vehicles) Swap(i, j int) {
    s[i], s[j] = s[j], s[i]
}

问题是当我使用新的结构Car实现Vehicle接口并尝试对一片汽车进行排序时我得到了这个异常

tmp/sandbox022796256/main.go:107: cannot use vehicles (type []Car) as type sort.Interface in argument to sort.Sort:
    []Car does not implement sort.Interface (missing Len method)

以下是完整代码:https://play.golang.org/p/KQb7mNXH01

更新

@Andy Schweig为我提出的问题提供了一个很好的答案,但我应该更明确地说我将JSON解组为一个Car结构片段,所以他的解决方案在这个更明确的案例中不起作用 (请参阅我的代码的更新链接)

3 个答案:

答案 0 :(得分:1)

扩展Andy的答案......如果您正在使用Go 1.8(或者可以选择更新项目),您可以使用新添加的sort.Slice函数来执行此操作,使用常规切片,就像您一样d来自解组JSON:https://golang.org/pkg/sort/#Slice

答案 1 :(得分:1)

问题在于Car实施Vehicle,但[]Car不是[]Vehicle。一个是对象切片,另一个是接口切片。 Andy Scheweig说,你需要GetVehicles来返回Vehicle([] Vehicle)。您可以在GetVehicles内进行转换,然后如果您需要汽车,可以输入断言。

对您的代码进行了一些更改,现在可以根据需要进行操作。

https://play.golang.org/p/fM8EhSfsCU

答案 2 :(得分:0)

即使[]Car实现了Vehicles接口,也不能使用[]Vehicle Car(或Vehicle)的GetVehicles。 (即使元素类型兼容,切片类型也是不同的类型,类型必须完全匹配。)

幸运的是,修复代码很容易。您只需将func GetVehicles() Vehicles { return Vehicles{ Car{ CarManufacturer: "Chevrolet", CarModel: "Corvette", CarYear: 1965, CarColor: "Red", }, 的前几行更改为:

Car

这是有效的,因为Vehicle可以在需要Car的地方使用,因为Vehicle实现了I * coe接口。