Go语言 如何将派生类型的切片转换为基类型的切片?

ifmq2ha2  于 2023-09-28  发布在  Go
关注(0)|答案(1)|浏览(124)

假设我们有一个基类型,从它派生出另一个类型

type baseType struct {
}

type derivedType struct {
   baseType
}

如何将derivedType的切片转换为baseType?

derivedTypeSlice := []derivedType{}

func iTakeBaseSlice(baseSlice []baseType ) {
}

iTakeBaseSlice(???derivedTypeSlice)

@Gavin建议使用泛型

func iTakeBaseSlice[T baseType | derivedType](baseSlice []T) {
}

这种方法唯一的缺点是,函数必须知道将调用它的所有派生类型。这对于未导出的函数来说不是问题(最有可能的是未导出的函数知道在包中调用它的类型),但对于导出的函数来说是个问题。
我的想法是循环派生片并追加到基类型的新片中

derivedTypeSlice := []derivedType{}
baseTypeSlice := []baseTypeSlice{}
for _, derivedTypeElement := range derivedTGypeSlice {
   baseTypeSlice = append(baseTypeSlice, derivedTypeElement.baseType)
}
iTakeBaseSlice(baseTypeSlice)

这种方法的缺点是性能和内存损失。因为派生切片将被复制到基本切片中,因此使内存使用量加倍。追加操作(如果派生的切片是常量大小,则可以避免)在性能方面代价高昂。

jdzmm42g

jdzmm42g1#

结构嵌入不是子类化。一般来说,[]baseType[]derivedType是不可赋值的。
处理这个问题的一种方法是使用接口。对于接口数组,每个值都可以有自己的类型。您可以编写接受接口的函数,并使用方法与项(或反射)交互。所以你的列表类型可以是[]interface{...}(其中...是你需要的方法)
接口是两个指针:一个类型指针和一个指向值的指针。您还可以考虑是否只使用值指针。通过这种方式,您将创建一个指向“基类型”的指针列表,并将其传递给希望采用基类型的函数。所以它是[]*baseType
根据列表的大小,创建新列表并填充它可能比您想象的要快。基准测试,并找出答案!

相关问题