【问题标题】:Golang sorting slice of interfacesGolang 对接口切片进行排序
【发布时间】:2017-08-29 20:58:29
【问题描述】:

我用 Golang 编写了一个 CLI 工具来包装 API,我喜欢它的简单组合。现在我想合并另一个具有不同 JSON 结构的 API 以获得相似的值。我为要实现的结构创建了一个接口,但我不太了解 Golang 中的类型转换是如何工作的。

这是我整理的一个例子:

我有一个公开一些方法的通用接口 Vehicle

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

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

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 接口并尝试对 Cars 的一部分进行排序时,我得到了这个异常

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 结构的一部分,因此他的解决方案在这种更明确的情况下不起作用 (请参阅我的代码的更新链接)

【问题讨论】:

    标签: go interface casting type-conversion


    【解决方案1】:

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

    幸运的是,修复代码很容易。您只需将GetVehicles 的前几行更改为:

    func GetVehicles() Vehicles {
        return Vehicles{
            Car{
                CarManufacturer: "Chevrolet",
                CarModel:        "Corvette",
                CarYear:         1965,
                CarColor:        "Red",
            },
    

    这是可行的,因为Car 可以在需要Vehicle 的地方使用,因为Car 实现了Vehicle 接口。

    【讨论】:

    • 嘿@Andy Schweig,感谢您的回复。事实证明,我应该在我的示例中更明确一点,因为我将 json 解组为 Car 结构的一部分,我不能只返回它。我想我可以遍历这些并构建一个切片 Vehicle 来返回,但这似乎是一种浪费。看看我更新的例子,如果你有更好的答案,请告诉我play.golang.org/p/KQb7mNXH01
    【解决方案2】:

    扩展安迪的回答...如果您使用 Go 1.8(或可以选择为您的项目更新),您可以使用新添加的 sort.Slice 函数对常规切片执行此操作,就像您一样d 从解组 JSON 中获取:https://golang.org/pkg/sort/#Slice

    【讨论】:

      【解决方案3】:

      问题是Car实现了Vehicle,但[]Car不是[]Vehicle。一个是对象切片,另一个是接口切片。 正如 Andy Scheweig 所说,您需要 GetVehicles 来返回 Vehicles ([]Vehicle)。您可以在 GetVehicles 中进行转换,然后如果您需要 Cars,您可以进行类型断言。

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

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

      【讨论】:

        猜你喜欢
        • 2019-03-15
        • 2019-01-08
        • 1970-01-01
        • 2018-06-18
        • 2018-06-25
        • 1970-01-01
        • 1970-01-01
        • 2020-11-29
        • 1970-01-01
        相关资源
        最近更新 更多