如何从通道消耗的所有元素中构造切片(如Python的list
那样)?我可以使用这个辅助函数:
func ToSlice(c chan int) []int {
s := make([]int, 0)
for i := range c {
s = append(s, i)
}
return s
}
Run Code Online (Sandbox Code Playgroud)
但由于缺乏泛型,我不得不为每种类型写出来,不是吗?是否有内置函数来实现这一点?如果没有,我怎么能避免为我正在使用的每一种类型复制和粘贴上面的代码?
你可以让ToSlice()只在接口{}上工作,但你在这里保存的代码量可能会让你在其他地方花费很多.
func ToSlice(c chan interface{}) []interface{} {
s := make([]interface{}, 0)
for i := range c {
s = append(s, i)
}
return s
}
Run Code Online (Sandbox Code Playgroud)
http://play.golang.org/p/wxx-Yf5ESN上的完整示例
话虽这么说:正如@Volker在代码片段(haha)的评论中所说的那样,看起来似乎是以流式方式处理结果或者在发生器上"缓冲它们"而只是发送它切入通道.
如果您的代码中只有几个实例需要进行转换,那么复制几次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)
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
5243 次 |
最近记录: |