2016-11-04 33 views
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)) // works 
    f(chList...) // cannot use chList (type []chan int) as type []<-chan int in argument to f 
} 

看來我錯過了一些基本的東西,但我無法弄清楚什麼。如果該功能不能使用單向通道,爲什麼在第一種情況下不能使用它?

+2

這就是類型系統的工作原理。 'make(chan ...)'使有點「無向」(不是雙向的,無向的)頻道可分配給定向頻道,而「chList」是一個雙向頻道片段,不可分配給只接收頻道。你可以做'chList:= [] < - chan int {make(chan int),make(chan int)}'。 – Volker

回答

0

你錯過了方向,

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

但後來我無法在通道上發送(發送到只接收類型<-chan int)。爲什麼在不把它們放到一個切片中時工作? – olovp

+0

請參閱切片轉換http://stackoverflow.com/a/39950654/4466350。 –

+0

你永遠不應該製造一個定向通道,因爲它幾乎沒用。 – JimB

2

好了,現在看來,這具有的slice covariance in golack做。我的解決方案是將「非定向」通道切片轉換爲一段只讀通道。下面是一個完整的例子:

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) 
} 
相關問題