У меня есть функция:
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)
Это не удается, потому что мне нужно использовать reflection.BothDir внутри функции ( потому что я отправляю ему значения внутри f
), поэтому фактический тип - chan <something>
. Я хочу, чтобы пользователи этой функции видели только принимающую сторону канала. Есть ли способ «преобразовать» chan <something>
в <-chan <something>
перед возвратом из f
? Использование возвращаемого типа <-chan interface{}
не является вариантом, поскольку для перехода от этого типа к <-chan <something>
потребуется, чтобы пользователь f
создал другой канал и вручную sh значения в нем, но я хочу f
для использования в качестве однострочного.
РЕДАКТИРОВАТЬ:
Я также попытался сделать это как можно более общим, но я думаю, что должен быть подробнее c:
Я пытаюсь написать функцию, которая принимает фрагмент значений типа A и возвращает канал, заполненный значениями этого фрагмента. Он предназначен для использования в модульных тестах, поэтому меня не волнует необходимость использования отражения, но я действительно забочусь о том, чтобы тесты были как можно более краткими, что в моем конкретном случае означает рефакторинг кода инициализации, совместно используемого несколькими тестами. Точный код:
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 не сможет предотвратить это, но в основном я был интересно, была ли часть языка, которую я пропустил, что позволило бы мне предотвратить вышеуказанный случай.