关于在方法的receiver中使用泛型的问题

话不多说,直接贴代码

func main() {
    var a MySlice[string]
    a = append(a, "2")
    v := a.Sum()
    fmt.Println(v)
}

type MySlice[T int | float32 | string] []T

func (s MySlice[string]) Sum() int {
    var res int
    for _, v := range s {
        conv, _ := strconv.Atoi(v)
        res = res + conv
    }
    return res
}

问题:
在方法Sum()的receiver (s MySlice[string]) 中,把泛型类型 MySlice 中的 T 约束为 string
此时在 for _, v := range s 中, v 的类型应该是 string。 但是在 conv, _ := strconv.Atoi(v) 中会编译错误:

cannot use v (variable of type string constrained by int|float32|string) as type string in argument to strconv.Atoi

这是为什么呢? 难道在方法receiver中的类型不是这样用的吗? 有没有更好的例子可以解释如何正确在方法receiver中使用泛型?


我编辑了一下代码,发现好像在 receiver 中并不会对泛型起到约束作用…

func main() {
    var a MySlice[int]
    a = append(a, 1)
    v := a.Sum()
    fmt.Println(v)
}

type MySlice[T int | float32 | string] []T

func (s MySlice[string]) Sum() int {
    var res int
    for _, v := range s {
        fmt.Printf("%T\n", v)
    }
    return res
}

这里输出出来, for _, v := range sv 的类型是 int
那么receiver里的 s MySlice[string] 感觉其实是没有任何用处呀:sweat_smile:


再来一个有趣的现象:

func main() {
    var a MySlice[string]
    a = append(a, "2", "3")
    v := a.Sum()
    fmt.Println(v)
    fmt.Printf("%T\n", v)
}
type MySlice[T int | float32 | string] []T
func (s MySlice[int]) Sum() int {
    var res int
    for _, v := range s {
        res = res + v
    }
    return res
}

我写完这个代码,以为输出的内容是:

5
int

结果实际执行结果是:

23
string
讨论数量: 3
Mericustar

类型约束 和 类型参数 不能写在一起

1年前 评论

正确做法

import "github.com/spf13/cast"

type DataType interface{
    int | float32 | string
}

type MySlice[T DataType] []T
func (s MySlice[DataType]) Sum() int {
    var res int
    for _, v := range s {
        res = res + cast.ToInt(v)
    }
    return res
}
1年前 评论
Lichmaker (楼主) 1年前

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!