是否有可能从分配给的返回值推断类型参数?



假设我写了这样两个函数:

func ToInterfaceSlice[T any](s []T) []interface{} {
res := make([]interface{}, len(s))
for i, v := range s {
res[i] = v
}
return res
}
func FromInterfaceSlice[T any](s []interface{}) (res []T, err error) {
res = make([]T, len(s))
for i, v := range s {
vt, ok := v.(T)
if !ok {
return nil, fmt.Errorf("%v (type=%T) doesn't fit the target type %T", v, v, res)
}
res[i] = vt
}
return
}

当我从输入参数解析类型时,我可以简单地使用

var m = []int{1, 2, 3}
fmt.Println(ToInterfaceSlice(m))

编译器知道Tint

但是当我尝试从返回变量

传递类型时
var m []int
m, _ = FromInterfaceSlice([]interface{}{1, 2, 3})
fmt.Println(m)

编译器给出错误:

划痕。go:29:27: cannot infer T

必须在函数调用中显式传递类型:

var m []int
m, _ = FromInterfaceSlice[int]([]interface{}{1, 2, 3})
fmt.Println(m)

当接收变量不是接口时,从返回类型推断类型参数是否有困难?或者只是不执行,甚至故意不执行?

在注释后更新#1

我知道a, b := GenericFunc()不能引用返回值的类型。目前Go确实有"视情况而定"。Case是否需要从用户输入显式实例化。

type Set[T comparable] map[T]struct{}
func NewSet[T comparable](eles ...T) Set[T] {
s := make(Set[T])
for _, ele := range eles {
s[ele] = struct{}{}
}
return s
}

可以同时使用t := NewSet(1, 2, 3)t := NewSet[string](),但现在不能使用var t NewSet[float64] = NewSet(),因为这个

当前的类型推断规则是显式的。没有考虑返回值的使用方式:

类型推断基于

  • a类型参数列表
  • 用已知类型参数初始化的替换映射M,如果有
  • 普通函数参数列表(可能为空)(仅在函数调用的情况下)

从Go 1.18开始,可以简单地重写函数以接受所需类型的参数;这样做的好处是不会在函数体中隐藏分配:

func FromInterfaceSlice[T any](s []interface{}, dst []T) error {
if len(s) != len(dst) {
return errors.New("lengths don't match")
}
for i, v := range s {
vt, ok := v.(T)
if !ok {
return nil, fmt.Errorf("%v (type=%T) doesn't fit the target type %T", v, v, res)
}
dst[i] = vt
}
return nil
}

并传入具有所需长度的目标切片:

func main() {
src := []interface{}{1, 2, 3}
m := make([]int, len(src))
_ = FromInterfaceSlice(src, m)
fmt.Println(m)
}

如果你不能或不想事先确定切片的长度,你只能使用显式实例化:

var m []int
m, _ = FromInterfaceSlice[int]([]interface{}{1, 2, 3})
//                        ^^^ explicit type argument

类型参数仍然不能用:=速记声明来推断:

// what is m???
m, err := FromInterfaceSlice([]interface{}{1, 2, 3})

最新更新