场景:
Go 1.18 支持泛型
问题:
无法将数字转换为泛型。
说明:
我正在尝试移植我的general purpose库以支持泛型。我正在处理数字转换错误。
我定义了一个包含所有数字类型的包,如下所示:
package types
type Number interface {
int | int8 | int16 | int32 | int64 | uint | uint8 | uint16 | uint32 | uint64 | uintptr | float32 | float64
}
Run Code Online (Sandbox Code Playgroud)
我在处理泛型时没有什么特别的问题。我唯一不明白的是:
如何将定义的类型(如int)转换为泛型?
让我们假设以下示例:
// FindIndexValue is delegated to retrieve the index of the given value into the input array.
func FindIndexValue[T types.Number](array []T, value T) []T {
var indexs []T
for i := range array {
if array[i] == value {
indexs = append(indexs, i)
}
}
return indexs
}
Run Code Online (Sandbox Code Playgroud)
在上面的代码片段中,错误位于以下行:
...
for i := range array {
...
}
Run Code Online (Sandbox Code Playgroud)
这是因为内置函数迭代数组并返回给定位置的range索引 ( )。int
问题是:
如何将定义的类型(int在本例中)转换为泛型T?
错误:
cannot use i (variable of type int) as type T in argument to append
您可以像平常一样将值转换为参数类型。
来自提案类型转换:
在具有两个类型参数
From和 的函数中To,如果From 约束的类型集中的所有类型都可以转换为 To 约束的类型集中的所有类型,则 type 的From值可以转换为 type 的值。To
在这种情况下,你实际上没有 aFrom因为它是切片索引int;目标类型将是T(即使这可能不是您想要的,请参阅下面的原因)。当然int可以转换为 的T类型集,因为它仅包含数字类型(尽管在或 的情况下会截断或丢失精度!)int8float64
indexs = append(indexs, T(i))
Run Code Online (Sandbox Code Playgroud)
但是您的程序将索引切片声明为[]T,这意味着将您的通用函数实例化为:
is := FindIndexValue([]float64{1,5,7,9}, float64(9))
Run Code Online (Sandbox Code Playgroud)
将产生类型 的结果[]float64。由于返回的值是切片索引,并且始终为int,因此这没有多大意义。
更好的是简单地返回[]int:
func FindIndexValue[T Number](array []T, value T) []int {
var indices []int
for i := range array {
// match on the generically typed slice item
if array[i] == value {
// store slice indices as ints
indices = append(indexs, i)
}
}
return indices
}
Run Code Online (Sandbox Code Playgroud)
游乐场:https://gotipplay.golang.org/p/EykXppG2qJa
无论切片的元素类型如何,索引始终int为整数类型 ( )。所以结果类型应该是[]int.
你为什么想要这样[]T?如果T是uint8并且传递的切片包含超过 256 个元素,您甚至无法返回正确的索引。
func FindIndexValue[T types.Number](array []T, value T) []int {
var indices []int
for i, v := range array {
if v == value {
indices = append(indices, i)
}
}
return indices
}
Run Code Online (Sandbox Code Playgroud)