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

将通道的所有元素消耗到切片中

将通道的所有元素消耗到切片中

Go
鸿蒙传说 2021-07-09 18:21:26
如何从通道消耗的所有元素中构造一个切片(就像 Pythonlist那样)?我可以使用这个辅助函数:func ToSlice(c chan int) []int {    s := make([]int, 0)    for i := range c {        s = append(s, i)    }    return s}但是由于缺乏泛型,我必须为每种类型都编写它,不是吗?是否有实现此功能的内置函数?如果没有,如何避免为我使用的每种类型复制和粘贴上述代码?
查看完整描述

2 回答

?
慕少森

TA贡献2019条经验 获得超9个赞

如果您的代码中只有少数几个实例需要转换,那么将 7 行代码复制几次绝对没有错(或者甚至在使用它的地方内联它,这将其减少到 4 行代码并且可能是最易读的解决方案)。


如果你真的有很多类型的通道和切片之间的转换,并且想要一些通用的东西,那么你可以通过反射来做到这一点,代价是丑陋和在 ChanToSlice 的调用站点缺乏静态类型。


这是关于如何使用反射解决此问题的完整示例代码,并演示它适用于 int 通道。


package main


import (

    "fmt"

    "reflect"

)


// ChanToSlice reads all data from ch (which must be a chan), returning a

// slice of the data. If ch is a 'T chan' then the return value is of type

// []T inside the returned interface.

// A typical call would be sl := ChanToSlice(ch).([]int)

func ChanToSlice(ch interface{}) interface{} {

    chv := reflect.ValueOf(ch)

    slv := reflect.MakeSlice(reflect.SliceOf(reflect.TypeOf(ch).Elem()), 0, 0)

    for {

        v, ok := chv.Recv()

        if !ok {

            return slv.Interface()

        }

        slv = reflect.Append(slv, v)

    }

}


func main() {

    ch := make(chan int)

    go func() {

        for i := 0; i < 10; i++ {

            ch <- i

        }

        close(ch)

    }()

    sl := ChanToSlice(ch).([]int)

    fmt.Println(sl)

}



查看完整回答
反对 回复 2021-07-12
  • 2 回答
  • 0 关注
  • 190 浏览
慕课专栏
更多

添加回答

举报

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