我有一个功能:
func f(input interface{}) interface{} {
t := reflect.ChanOf(reflect.BothDir, <type that depends on input>)
c := reflect.MakeChan(t, ...)
// ... push things from input into c ...
return c
}
它创建一个通道,其元素类型取决于输入。它可以这样使用,但我希望它适用于任何类型,而不仅仅是int:x := f(1).(<-chan int)
失败是因为我必须在函数内部使用reflect.BothDir(因为我正在f
内部向其发送值),因此实际类型为chan <something>
。我只希望此功能的用户看到频道的接收端。从chan <something>
返回之前,有什么方法可以将<-chan <something>
“投射”到f
吗?使用<-chan interface{}
的返回类型不是一种选择,因为从该类型转到<-chan <something>
将需要f
的用户创建另一个通道并将值手动推入该通道,但我希望f
用作单线。编辑:
我也尝试使这尽可能通用,但是我想我必须更具体:
我正在尝试编写一个函数,该函数采用类型A的值的一个 slice ,并返回一个填充有该 slice 的值的通道。它打算在单元测试中使用,因此,我不必在乎必须使用反射,但是我确实在乎使测试尽可能简洁,这在我的特定情况下意味着重构由多个测试共享的初始化代码。确切的代码:
func gen(input interface{}) interface{} {
xs := reflect.ValueOf(input)
chanType := reflect.ChanOf(reflect.BothDir, xs.Type().Elem())
out := reflect.MakeChan(chanType, 0)
go func() {
for i := 0; i < xs.Len(); i++ {
x := xs.Index(i)
out.Send(i)
}
out.Close()
}
return out.Interface()
}
现在,如果我想测试一个函数g(<-chan int)
,我以前必须在其中编写values := <input generated by quick.check>
in := make(chan int)
go func() {
for _, value := range values {
in <- value
}
close(in)
}()
g(in)
我现在确实可以简单地打电话g(gen(values).(chan int))
而且效果很好。这是因为gen
的返回类型是chan int
,它将隐式转换为<-chan int
。我的问题是关于这样的情况:o := gen([]int{1, 1, 2, 3}).(chan int)
o <- 5 // You're not supposed to do that, sending to o is exclusive to the inside of the gen function
g(o)
我承认这种情况非常小众,即使Go无法提供防止这种情况的方法,我也会没事的,但是我主要是想知道如果我错过了某种语言的一部分,可以让我防止上述情况。 最佳答案
没有反射,您将使用(可能是隐式的)类型转换:
func sliceToChan(xs []int) <-chan int {
c := make(chan int)
// ...
return (<-chan int)(c) // or just `return c` for the implicit conversion
}
通过反射做同样的事情,即使用Convert:package main
import (
"fmt"
"reflect"
)
func main() {
x := sliceToChan([]int{1}).(<-chan int)
fmt.Println(cap(x))
}
func sliceToChan(input interface{}) interface{} {
xs := reflect.ValueOf(input)
elemType := xs.Type().Elem()
t := reflect.ChanOf(reflect.BothDir, elemType)
c := reflect.MakeChan(t, xs.Len())
for i := 0; i < xs.Len(); i++ {
x := xs.Index(i)
c.Send(x)
}
c.Close()
recvOnly := c.Convert(reflect.ChanOf(reflect.RecvDir, elemType))
return recvOnly.Interface()
}
在操场上尝试:https://play.golang.org/p/RDaAA_l9ghN关于go - 手动将chan转换/衰减到<-chan,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/63285586/