通用切片转换功能可以吗?

问题描述 投票:0回答:1

假设我们有两个派生自 int 的命名类型:

type Number1 int
type Number2 int

由于它们的底层类型相同,因此它们可以互相分配,所以这是可行的

var x Number1 = 42
var y Number2 = Number2(x)

但是,如果我们有切片,它们就不能直接分配:

sl1 := []Number1{1, 2, 3}
sl2 := []Number2(sl1) // doesn't work

但是我们可以复制切片:

sl2 := make([]Number2, len(sl1))
for i, v := range sl1 {
    sl2[i] = Number2(v)
}

我们甚至可以在整数上定义一个通用函数来进行转换:

func Convert[To ~int, From ~int](from []From) []To {
    to := make([]To, len(from))
    for i, v := range from {
        to[i] = To(v)
    }
    return to
}

并像这样使用它:

var sl2 []Number2 = Convert[Number2](sl1)
。这很好用。

我的问题是:有没有办法让 Convert 可以处理任何 2 个泛型类型 From/To(不仅仅是基础类型为 int 的类型),只要 From 可分配给 To?

我尝试了一些方法,但没能成功。基本上我想要的是这样的

func Convert[To ~E, From ~E, E any](from []From) []To { // invalid!
    ...
}

除非这是不允许的,因为 E 不能是 ~E 中的类型参数。

那么,有解决办法吗?如果是,请提供示例,如果否,请解释为什么不可能。

go generics
1个回答
0
投票

Go 规范声明

在 ~T 形式的术语中,T 的底层类型必须是其自身,并且 T 不能是接口。

由于类型参数不是“类型本身”,因此

[To ~E, From ~E, E any]
是无效表达式。

© www.soinside.com 2019 - 2024. All rights reserved.