【问题标题】:How can I pass a channel slice to a function as variadic?如何将通道切片作为可变参数传递给函数?
【发布时间】:2016-11-04 18:01:06
【问题描述】:

如果我有一个函数需要多个只读通道(例如用于通道聚合),为什么我不能用一个通道切片调用这个函数,比如

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
}

我似乎遗漏了一些基本的东西,但我不知道是什么。如果函数不能接受单向通道,为什么在第一种情况下不能接受?

【问题讨论】:

  • 这就是类型系统的工作原理。 make(chan ...) 有点“无向”(非双向,无向)通道,可分配给定向通道,而 chList 是双向通道的一部分,不可分配给仅接收通道。你可以做chList := []&lt;-chan int{make(chan int), make(chan int)}

标签: go


【解决方案1】:

好的,所以它似乎与slice covariance in go 中的lack 有关。我的解决方案是将“非定向”通道切片转换为只读通道切片。完整示例如下:

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】:

    你错过了方向,

    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...) 
    }
    

    【讨论】:

    • 但是我不能在频道上发送(发送到仅接收类型
    • 你永远不应该 make 定向频道,因为它几乎没用。
    猜你喜欢
    • 1970-01-01
    • 2013-01-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-01-17
    • 2018-06-15
    • 1970-01-01
    • 2017-02-10
    相关资源
    最近更新 更多