为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

Go
蓝山帝景 2022-12-13 10:41:55
假设我写了两个这样的函数: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))编译器知道T是int.但是,当我尝试从返回变量传递类型时    var m []int    m, _ = FromInterfaceSlice([]interface{}{1, 2, 3})    fmt.Println(m)编译器报错:.\scratch.go:29:27: 无法推断 T我必须在函数调用中显式传递类型:    var m []int    m, _ = FromInterfaceSlice[int]([]interface{}{1, 2, 3})    fmt.Println(m)当接收者变量不是接口时,从返回类型推断类型参数有什么困难吗?还是干脆不执行,甚至故意不执行?评论后更新#1我知道a, b := GenericFunc()不能引用返回值的类型。目前 Go 确实有“这取决于”情况是否需要来自用户输入的显式实例化。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)and t := NewSet[string](),但var t NewSet[float64] = NewSet()现在不行,因为这个
查看完整描述

1 回答

?
猛跑小猪

TA贡献1858条经验 获得超8个赞

当前的类型推断规则是明确的。不考虑如何使用返回值:

类型推断是基于

  • 类型参数列表

  • 用已知类型参数初始化的替换映射 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})


查看完整回答
反对 回复 2022-12-13
  • 1 回答
  • 0 关注
  • 96 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信