英文:
Golang sorting slice of interfaces
问题
我用Golang编写了一个CLI工具,用于封装一个API,我喜欢它的简单性。现在我想将另一个具有不同JSON结构的API整合进来,以获取类似的值。我为这些结构创建了一个接口,但我不太理解Golang中的类型转换是如何工作的。
这是我编写的一个示例:
我有一个公共接口Vehicle,它公开了一些方法:
type Vehicle interface {
Manufacturer() string
Model() string
Year() int
Color() string
String() string
}
我还想对所有实现了该接口的结构进行排序,所以我添加了一个实现了sort接口的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接口,并尝试对一个Car结构的切片进行排序时,我得到了以下异常:
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结构的切片,所以他的解决方案在这种更明确的情况下不适用(请参见我代码的更新链接)。
英文:
I wrote a CLI tool in Golang to wrap an API and I love how simple it was to put together. Now I want to incorporate another API with a different JSON structure to get similar values. I created an interface for the structs to implement, but I don't quite understand how the type casting works in Golang.
Here is an example I put together:
I have a common interface Vehicle that exposes some methods
type Vehicle interface {
Manufacturer() string
Model() string
Year() int
Color() string
String() string
}
I also want to sort all structs that implement this interface so I added a Vehicles type that implements the sort interface
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]
}
The issue is when I implement the Vehicle interface with a new struct Car and try to sort a slice of Cars I get this exception
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)
Here is the full code: https://play.golang.org/p/KQb7mNXH01
Update:
@Andy Schweig provided a good answer to the problem I posed, but i should have been more explicit that I am unmarshalling JSON into a slice of Car structs so his solution doesn't work in this more explicit case
( Please see the updated link to my code )
答案1
得分: 1
如果你正在使用Go 1.8(或者有更新项目的选项),你可以使用新添加的sort.Slice函数来对常规切片进行排序,就像你从解析JSON中获得的切片一样。详见:https://golang.org/pkg/sort/#Slice
英文:
Extending on Andy's answer... If you're using Go 1.8 (or have the option to update for your project), you can use the newly-added sort.Slice function to do this with regular slices, like you'd get from unmarshalling JSON: https://golang.org/pkg/sort/#Slice
答案2
得分: 1
问题在于Car
实现了Vehicle
接口,但[]Car
不是[]Vehicle
。一个是对象的切片,另一个是接口的切片。
正如Andy Scheweig所说,你需要让GetVehicles
返回Vehicles
([]Vehicle
)。你可以在GetVehicles
内部进行转换,之后如果你需要Cars
,可以进行类型断言。
对你的代码进行了一些修改,现在按照你的需求工作。
https://play.golang.org/p/fM8EhSfsCU
英文:
The problem is that Car
implements Vehicle
, but []Car
is not []Vehicle
. One is a slice of objects and the other is a slice of interfaces.
What you need as Andy Scheweig said, you need GetVehicles to return Vehicles ([]Vehicle). You can do the conversion inside the GetVehicles
and afterwards if you need the Cars you can do type assertion.
Made some changes to your code, and works as you need it now.
答案3
得分: 0
你不能在期望Vehicles
(或[]Vehicle
)的地方使用[]Car
,即使Car
实现了Vehicle
接口。(尽管元素类型是兼容的,切片类型是不同的类型,类型必须完全匹配。)
幸运的是,修复你的代码很容易。你只需要将GetVehicles
的前几行改为以下内容:
func GetVehicles() Vehicles {
return Vehicles{
Car{
CarManufacturer: "Chevrolet",
CarModel: "Corvette",
CarYear: 1965,
CarColor: "Red",
},
这样做是有效的,因为Car
可以在期望Vehicle
的地方使用,因为Car
实现了Vehicle
接口。
英文:
You can't use []Car
where Vehicles
(or []Vehicle
) is expected, even though Car
implements the Vehicle
interface. (Even though the element types are compatible, the slice types are different types, and types must match exactly.)
Fortunately, it's easy to fix your code. You just have to change the first few lines of GetVehicles
to this:
func GetVehicles() Vehicles {
return Vehicles{
Car{
CarManufacturer: "Chevrolet",
CarModel: "Corvette",
CarYear: 1965,
CarColor: "Red",
},
This works because Car
can be used where Vehicle
is expected, because Car
implements the Vehicle
interface.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论