web-dev-qa-db-ja.com

go(golang)の関数で引数としてチャネルを渡すさまざまな方法

私はいくつかの囲codeコードを読んでおり、囲channelsチャンネルを渡すいくつかの異なる方法を言っていました。おそらく同じかもしれませんが、オンラインでドキュメントを見つけることができなかったので、何か違いがあるのではないかと思っていました。

1)

func serve(ch <-chan interface{}){ //do stuff }

2)

func serve(ch chan<- interface{}){ //do stuff }

3)

func serve(ch chan interface{}){ //do stuff }

4)

func server(ch *chan interface{}){ //do stuff}

それらの違いは何なのか、同じことをするための単なる同等の方法であるかどうか、つまり、異なるゴルーチンの周りにチャネルを渡すのかと思っていました。

注:chan、map、slice、またはfunctionの値にポインターを渡す理由はないことを認識しています。これらはすべてポインターを内部に含む参照型であるためです(呼び出し先を変更する場合は例外です)参照型ヘッダー)。私がそれを提供した唯一の理由は、完全性のためです(つまり、チャネルをパラメータとして渡そうとするあらゆる方法を実際に提供し、できればこれを行うすべての方法を参照して比較することを疑問視します)。

45
Charlie Parker

これらは異なるタイプのチャネルです。 http://golang.org/ref/spec#Channel_types を参照してください。ポインターの場合:一般的ではありませんが、関数内からチャネルを変更する場合に役立ちます(実際に見たことはありません)。

25
Volker

可能な限りどこにでも方向を渡すことを常にお勧めします。

func serve(ch <-chan SomeType) { /*do stuff*/ }

func serve(ch chan<- SomeType) { /*do stuff*/ }

矢印<-chanまたはchan<-、あなたは3つのことを達成しています:

  • パラメーターがチャネルのendであることを明確にしています。
  • あなたは明確に表現していますwhich endが提供されています。
  • チェックのためにコンパイラに詳細情報を提供しています。関数本体がチャネルの間違った終端を使用しようとすると、コンパイラはエラーを発生させる可能性があります。

これらは、可能な場合はいつでもチャンネルの終わりを示す正当な理由です。

3番目のケースは、チャネルの終わりを指定するnotを示しています。これにより、チャネルの両端にアクセスできるようになります。これは場合によっては正しくなりますが、場合によっては偶発的なエラーにつながる可能性があります。

4番目のケースは、ポインターをチャネルに渡すことは非常に珍しく、おそらく少し奇妙です。チャンネルを変更する場合は、代わりに戻りパラメーターとしてチャンネルを含める方が明確です。

56
Rick-777

経験則:矢印は、データがチャネルに入る(出力)か、出る(入力)かを示します。矢印は汎用チャンネルではありません。

chan <-          writing to channel (output channel)
<- chan          reading from channel (input channel)
chan             read from or write to channel (input/output channel)
21
smishra