2016-11-04 12 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

、[OK]を

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

しかし、私はチャネルを送信することはできません(受信専用のタイプ< - ちょっと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) 
} 
関連する問題