use*_*572 5 generics type-conversion go
我厌倦了编写像 []int32 -> []int64 这样的手动切片转换,因为在很多情况下您需要将切片与其他类型一起使用。所以我尝试为此编写一个通用函数:
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
}
Run Code Online (Sandbox Code Playgroud)
并想像这样使用它
a := []int{1, 2, 3, 4, 5}
var b []int64 = convertSlice[int, int64](a)
Run Code Online (Sandbox Code Playgroud)
但我无法编译它,编译器说./prog.go:8:14: cannot convert t1[i] (variable of type T1 constrained by any) to type T2
那么,我该如何解决这个问题呢?
实例: https: //go.dev/play/p/YYOLFjYt4mq
当然,我可以为每个基本类型编写单独的函数,例如:
func convertNumericSlice[T1, T2 constraints.Integer | constraints.Float](t1 []T1) []T2 {}
func convertStringSlice[T1, T2 ~string](t1 []T1) []T2 {}
Run Code Online (Sandbox Code Playgroud)
但这看起来根本不像很酷的通用方式。
无法转换具有任意约束的类型参数。规范提到(转换):
\n\n\n[...] 如果满足以下条件之一,x 也可以转换为 T 类型:
\n\n
\n- V 和 T 都是类型参数, V 的类型集中的每种类型的值都可以转换为 T 的类型集中的每种类型。
\n
如果 和T1都T2受到 的约束any,则两个类型集实际上都包含任何可能的类型。
即使convertSlice函数的特定实例化可能有效,编译器也无法静态证明转换始终T2(t1)有效。理论上,您可以实例化,然后字符串显然无法转换为函数通道。convertSlice[string, chan func()]
编写 catch-all 函数的唯一方法是在CanConvert方法中使用反射,但您将需要决定如何处理CanConvertreturns 的情况false。恐慌?返回零值?
如果您选择使用泛型,那么您就已经做出了类型安全的选择,因此引入反射似乎是违反直觉的。对于泛型,您必须为每组可转换基础类型编写函数。主要特殊情况有:
\n数字:
\ntype Number interface {\n constraints.Integer | constraints.Float\n}\n\nconvertNumbers[T1, T2 Number](t1 []T1) []T2 {}\nRun Code Online (Sandbox Code Playgroud)\n字符串 \xe2\x80\x94 它是字节切片和符文切片的特殊情况,但字节切片和符文切片不能相互转换,所以这里需要两个函数):
\nconvertStrings[T1, T2 ~string | ~[]byte](t1 []T1) []T2 {}\n// or\nconvertStrings[T1, T2 ~string | ~[]rune](t1 []T1) []T2 {}\nRun Code Online (Sandbox Code Playgroud)\n复杂的:
\nconvertComplex[T1, T2 ~complex64 | ~complex128](t1 []T1) []T2 {}\nRun Code Online (Sandbox Code Playgroud)\n
| 归档时间: |
|
| 查看次数: |
5445 次 |
| 最近记录: |