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

如何从通道消耗的所有元素中构造一个切片(就像 Pythonlist那样)?我可以使用这个辅助函数:


func ToSlice(c chan int) []int {

    s := make([]int, 0)

    for i := range c {

        s = append(s, i)

    }

    return s

}

但是由于缺乏泛型,我必须为每种类型都编写它,不是吗?是否有实现此功能的内置函数?如果没有,如何避免为我使用的每种类型复制和粘贴上述代码?


鸿蒙传说
浏览 201回答 2
2回答

慕少森

如果您的代码中只有少数几个实例需要转换,那么将 7 行代码复制几次绝对没有错(或者甚至在使用它的地方内联它,这将其减少到 4 行代码并且可能是最易读的解决方案)。如果你真的有很多类型的通道和切片之间的转换,并且想要一些通用的东西,那么你可以通过反射来做到这一点,代价是丑陋和在 ChanToSlice 的调用站点缺乏静态类型。这是关于如何使用反射解决此问题的完整示例代码,并演示它适用于 int 通道。package mainimport (&nbsp; &nbsp; "fmt"&nbsp; &nbsp; "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{} {&nbsp; &nbsp; chv := reflect.ValueOf(ch)&nbsp; &nbsp; slv := reflect.MakeSlice(reflect.SliceOf(reflect.TypeOf(ch).Elem()), 0, 0)&nbsp; &nbsp; for {&nbsp; &nbsp; &nbsp; &nbsp; v, ok := chv.Recv()&nbsp; &nbsp; &nbsp; &nbsp; if !ok {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return slv.Interface()&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; slv = reflect.Append(slv, v)&nbsp; &nbsp; }}func main() {&nbsp; &nbsp; ch := make(chan int)&nbsp; &nbsp; go func() {&nbsp; &nbsp; &nbsp; &nbsp; for i := 0; i < 10; i++ {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ch <- i&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; close(ch)&nbsp; &nbsp; }()&nbsp; &nbsp; sl := ChanToSlice(ch).([]int)&nbsp; &nbsp; fmt.Println(sl)}
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go