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

2024-02-04

Scenario:
支持泛型的 Go 1.18

Problem:
无法将数字转换为泛型。

解释:
我正在尝试移植我的general purpose支持泛型的库。我正在处理数字转换错误。

我定义了一个包含所有数字类型的包,如下所示:

package types

type Number interface {
    int | int8 | int16 | int32 | int64 | uint | uint8 | uint16 | uint32 | uint64 | uintptr | float32 | float64
}

我在处理泛型时没有什么特别的问题。我唯一不明白的是:
如何转换定义的类型(例如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
}

在上面的代码片段中,错误位于以下行:

 ...
 for i := range array {
   ...
}

这是因为range内置迭代数组并返回索引 (int) 的给定位置。

问题是:
如何转换定义的类型(int在这种情况下)到通用T? Error:
cannot use i (variable of type int) as type T in argument to append


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

从提案来看类型转换 https://go.googlesource.com/proposal/+/refs/heads/master/design/43651-type-parameters.md#type-conversions:

在具有两个类型参数的函数中From and To,类型的值From可以转换为类型的值To if From约束的类型集中的所有类型都可以转换为To约束的类型集中的所有类型。

在这种情况下,你实际上没有From因为它是切片索引int;目的地类型将是T(即使这可能不是您想要的,请参阅下面的原因)。当然int可以转换为T的类型集,因为它仅包含数字类型(尽管截断或精度损失 https://go.dev/ref/spec#Conversions的情况下int8 or float64!)

indexs = append(indexs, T(i))

但是你的程序将索引切片声明为[]T,这意味着将通用函数实例化为:

is := FindIndexValue([]float64{1,5,7,9}, float64(9))

将产生类型的结果[]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
}

操场:https://gotipplay.golang.org/p/EykXppG2qJa https://gotipplay.golang.org/p/EykXppG2qJa

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

将类型(int、float 等)转换为 `T` [go1.18] 的相关文章

随机推荐