我厌倦了编写像[]int32->[]int64这样的手动切片转换,因为在很多情况下,您需要将Slice与另一种类型一起使用. 因此,我try 为此编写一个泛型函数:

func convertSlice[T1 any, T2 any](t1 []T1) []T2 {
    t2 := make([]T2, len(t1))
    for i := range t1 {
        t2[i] = T2(t1[i])
    }
    return t2
}

并想像使用它一样使用它

a := []int{1, 2, 3, 4, 5}
var b []int64 = convertSlice[int, int64](a)

但是我不能编译它,编译器说./prog.go:8:14: cannot convert t1[i] (variable of type T1 constrained by any) to type T2

那么,我怎么才能解决这个问题呢?

现场示例:https://go.dev/play/p/YYOLFjYt4mq

当然,我可以 for each 基本类型编写单独的函数,如下所示:

func convertNumericSlice[T1, T2 constraints.Integer | constraints.Float](t1 []T1) []T2 {}
func convertStringSlice[T1, T2 ~string](t1 []T1) []T2 {}

但这看起来一点也不像是很酷的通用化方式.

推荐答案

不能使用任意约束来转换类型参数.该规范提到(conversions):

[.]如果符合以下条件之一,也可以将X转换为类型T:

  • V和T都是类型参数,值为each type in V's type set can be converted to each type in T's type set.

如果T1T2都被约束为any,则两个类型集实际上都包括任何可能类型.

即使convertSlice函数的特定实例化可能有效,编译器也不能静态地证明转换T2(t1)always有效的.理论上,您可以实例化convertSlice[string, chan func()],然后字符串显然不能转换为函数通道.

编写通用函数的唯一方法是在CanConvert方法中使用反射,但您需要决定如何处理CanConvert返回false的情况.惊慌失措?是否返回零值?

如果您 Select 使用泛型,您就已经在 Select 类型安全,因此引入反射似乎有悖于直觉.对于泛型,您确实必须为每组可转换的基础类型编写函数.主要的特殊情况是:

数字:

type Number interface {
    constraints.Integer | constraints.Float
}

convertNumbers[T1, T2 Number](t1 []T1) []T2 {}

字符串-它是针对字节片和符号片的特殊大小写,但字节片和符号片不能相互转换,因此这里需要两个函数):

convertStrings[T1, T2 ~string | ~[]byte](t1 []T1) []T2 {}
// or
convertStrings[T1, T2 ~string | ~[]rune](t1 []T1) []T2 {}

复杂:

convertComplex[T1, T2 ~complex64 | ~complex128](t1 []T1) []T2 {}

Go相关问答推荐

Golang Cososdb-gremlin连接

Go汇编器命名为Constants

错误.如果它包含切片,则返回FALSE

关于如何使用 Service Weaver 设置多个不同侦听器的问题

`docker system df` 与 `/system/df` (docker api 端点)

在VSCode中如何使用特定的文件名提供编译命令

用于提取 <*n 的正则表达式(其中 n 是一个数字)

当填充通道的函数调用未嵌入 goroutine 时,为什么我会遇到死锁?

你如何在 Golang 代码中测试 filepath.Abs​​ 失败?

判断一个区域内的纬度/经度点

使用go doc命令查看示例函数?

函数超时和 goroutine 泄漏

github.com/rs/zerolog 字段的延迟判断

合并几千万文件最快的方法是什么

使用 Go 读取 TOML 文件时结果为空

go 堆栈跟踪:在某些函数调用参数或返回值之后的问题(?)标记是什么意思?

如何使路径/不匹配 Golang net/http 中所有其他不匹配的路径

测试包外文件时的 Golang 测试覆盖率

如何使用通用字段初始化匿名struct数组

在 Go 泛型中,如何对联合约束中的类型使用通用方法?