gpt4 book ai didi

go - 如何对具有共同字段的空接口(interface) slice 进行排序?

转载 作者:行者123 更新时间:2023-12-01 20:23:49 24 4
gpt4 key购买 nike

我有多个结构:

type FooStruct struct {
ID int
Field1 int
CommonID int
}

type BarStruct struct {
ID int
Field2 int
CommonID int
}

type FighterStruct struct {
ID int
Field3 int
CommonID int
}

1- 它们都被保存在不同的 slice 中: sliceOfFooStruct 、 sliceOfBarStruct 、 sliceofFighterStruct
2-我正在遍历每个 slice 并将它们未排序的插入到一个公共(public) var commonSlice []interface{}
3-然后我需要按 CommonID​​ 将它们排序到该 slice 中,这就是我卡住的地方。
我正在尝试做:
sort.Slice(commonSlice, func(i, j int) bool { return commonSlice[i].CommonID > commonSlice[j].CommonID })
但我得到了错误 commonSlice[i].CommonID undefined (type interface {} is interface with no methods)我也尝试过在做 commonSlice[i].CommonID​​.(int) 的情况下强制转换类型,但它也不起作用。
尝试过类似 this也使用匿名结构和 CommonID​​ 字段,但它不起作用。
如果我直接转换正在比较的实际结构的类型,我会假设它可以工作,但是硬编码类型会破坏 "commonSlice"的全部目的。
那是怎么做的?我应该做不同的事情吗?

最佳答案

由于您的 commonSlice 的元素类型是 interface{}您无法访问值的任何字段,因为它允许存储任何值,甚至是非结构的值。
一种不鼓励的方法是使用反射来访问 CommonID场,但这又丑又慢。作为引用,它的外观如下:

all := []interface{}{
FooStruct{11, 22, 31},
BarStruct{21, 32, 33},
FighterStruct{21, 32, 32},
}

sort.Slice(all, func(i, j int) bool {
commonID1 := reflect.ValueOf(all[i]).FieldByName("CommonID").Int()
commonID2 := reflect.ValueOf(all[j]).FieldByName("CommonID").Int()
return commonID1 > commonID2
})

fmt.Println(all)
此输出(在 Go Playground 上尝试):
[{21 32 33} {21 32 32} {11 22 31}]
而是创建一个接口(interface)来描述访问 CommonID 的方法。 field :
type HasCommonID interface {
GetCommonID() int
}
并让你的 struts 实现这个接口(interface):
func (f FooStruct) GetCommonID() int     { return f.CommonID }
func (b BarStruct) GetCommonID() int { return b.CommonID }
func (f FighterStruct) GetCommonID() int { return f.CommonID }
并将您的值存储在此接口(interface)的一部分中:
all := []HasCommonID{
FooStruct{11, 22, 31},
BarStruct{21, 32, 33},
FighterStruct{21, 32, 32},
}
然后你可以使用 GetCommonID()less() 中访问它的方法功能:
sort.Slice(all, func(i, j int) bool {
return all[i].GetCommonID() > all[j].GetCommonID()
})
这将输出相同,请在 Go Playground 上尝试.
这更清洁、更快、可扩展。
为避免重复,您可以将公共(public)字段和方法“外包”到结构并将其嵌入到所有支柱中:
type Common struct {
CommonID int
}

func (c Common) GetCommonID() int { return c.CommonID }

type FooStruct struct {
ID int
Field1 int
Common
}

type BarStruct struct {
ID int
Field2 int
Common
}

type FighterStruct struct {
ID int
Field3 int
Common
}
注: GetCommonID()仅定义一次,用于 Common ,其他类型不需要添加。然后使用它:
all := []HasCommonID{
FooStruct{11, 22, Common{31}},
BarStruct{21, 32, Common{33}},
FighterStruct{21, 32, Common{32}},
}

sort.Slice(all, func(i, j int) bool {
return all[i].GetCommonID() > all[j].GetCommonID()
})
输出是一样的,试试 Go Playground .
这还允许您在单个位置 ( Common) 中扩展公共(public)字段和方法列表,而无需进一步重复。

关于go - 如何对具有共同字段的空接口(interface) slice 进行排序?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63338244/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com