将类型(int、float 等)转换为 `T` [go1.18]

ale*_*avi 6 generics go

场景
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

bla*_*een 6

您可以像平常一样将值转换为参数类型。

来自提案类型转换

在具有两个类型参数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


icz*_*cza 5

无论切片的元素类型如何,索引始终int为整数类型 ( )。所以结果类型应该是[]int.

你为什么想要这样[]T?如果Tuint8并且传递的切片包含超过 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)