英文:
How can I pass a channel slice to a function as variadic?
问题
如果我有一个函数,它接受一些只读通道的数量(例如用于通道聚合),为什么我不能用通道切片来调用这个函数呢?
package main
func f(in ...<-chan int) {
// do something
}
func main() {
chList := []chan int{make(chan int), make(chan int)}
f(make(chan int), make(chan int)) // 可行
f(chList...) // 无法将 chList(类型为 []chan int)作为参数传递给 f 中的类型 []<-chan int
}
我似乎缺少一些基本的东西,但我无法弄清楚是什么。如果函数不能接受单向通道,为什么在第一个例子中可以接受它们呢?
英文:
If I have a function that takes a number of read only channels (for example for channel aggregation), why can't I call this function with a slice of channels, like
package main
func f(in ...<-chan int) {
// do something
}
func main() {
chList := []chan int{make(chan int), make(chan int)}
f(make(chan int), make(chan int)) // works
f(chList...) // cannot use chList (type []chan int) as type []<-chan int in argument to f
}
It seems I'm missing something fundamental but I can't figure out what. If the function can't take unidirectional channels, why can it take them when not in the first case?
答案1
得分: 1
好的,下面是翻译好的代码部分:
package main
import (
"fmt"
"time"
)
func f(in ...<-chan int) chan int {
fmt.Println("通道数量:", len(in))
out := make(chan int)
for _, ch := range in {
go func(ch <-chan int) {
for i := range ch {
out <- i
}
}(ch)
}
return out
}
func chConv(channels ...chan int) []<-chan int {
ret := make([]<-chan int, len(channels))
for n, ch := range channels {
ret[n] = ch
}
return ret
}
func main() {
chList := []chan int{make(chan int), make(chan int)}
roChans := chConv(chList...)
agg := f(roChans...)
go func() {
for i := range agg {
fmt.Println("收到:", i)
}
}()
for i := 0; i < 10; i++ {
for _, ch := range chList {
ch <- i
}
}
time.Sleep(1 * time.Second)
}
这段代码涉及到了Go语言中切片协变性的问题。解决方案是将"nondirectional"通道的切片转换为只读通道的切片。完整的示例代码如上所示。
英文:
Ok, so it seems it has to do with lack of slice covariance in go. My solution is to type convert the slice of "nondirectional" channels into a slice of readonly channels. Full example below:
package main
import (
"fmt"
"time"
)
func f(in ...<-chan int) chan int {
fmt.Println("number of channels:", len(in))
out := make(chan int)
for _, ch := range in {
go func(ch <-chan int) {
for i := range ch {
out <- i
}
}(ch)
}
return out
}
func chConv(channels ...chan int) []<-chan int {
ret := make([]<-chan int, len(channels))
for n, ch := range channels {
ret[n] = ch
}
return ret
}
func main() {
chList := []chan int{make(chan int), make(chan int)}
roChans := chConv(chList...)
agg := f(roChans...)
go func() {
for i := range agg {
fmt.Println("got:", i)
}
}()
for i := 0; i < 10; i++ {
for _, ch := range chList {
ch <- i
}
}
time.Sleep(1 * time.Second)
}
答案2
得分: 0
你错过了方向,
package main
func f(in ...<-chan int) {
// 做一些事情
}
func main() {
chList := []<-chan int{make(<-chan int), make(<-chan int)}
f(make(<-chan int), make(<-chan int))
f(chList...)
}
英文:
you missed the direction,
package main
func f(in ...<-chan int) {
// do something
}
func main() {
chList := []<-chan int{make(<-chan int), make(<-chan int)}
f(make(<-chan int), make(<-chan int))
f(chList...)
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论