我有一个功能:

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/

10-11 19:55