猿问

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

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


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()现在不行,因为这个


蓝山帝景
浏览 97回答 1
1回答

猛跑小猪

当前的类型推断规则是明确的。不考虑如何使用返回值:类型推断是基于类型参数列表用已知类型参数初始化的替换映射 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 []intm, _ = FromInterfaceSlice[int]([]interface{}{1, 2, 3})//                        ^^^ explicit type argument此外,类型参数仍然无法通过:=简写声明推断出来:// what is m???m, err := FromInterfaceSlice([]interface{}{1, 2, 3})
随时随地看视频慕课网APP

相关分类

Go
我要回答