ファンインパターンを見てみましょう。これは、複数のスレッドからの関連データをまとめる必要がある場合に、Go で非常に役立ちます。
たとえば、異なるサービスに対して複数の API 呼び出しを実行し、その結果を結合する必要があるとします。
これは実装が非常に簡単なパターンですが、チャネルの処理方法に注意する必要があります。デッドロック状態になりやすいです。
// produce is used to simulate the different data sources func produce(id int) chan int { ch := make(chan int) go func() { for i := 0; i < 10; i++ { ch <- id*10 + i } fmt.Printf("producer %d done\n", id) close(ch) // this is important!!! }() return ch } func fanin(inputs ...chan int) chan int { output := make(chan int) var wg sync.WaitGroup for i, input := range inputs { wg.Add(1) go func() { for value := range input { output <- value } fmt.Printf("done merging source %d\n", i) wg.Done() }() } go func() { wg.Wait() close(output) // this is important!!! }() return output } func main() { input1 := produce(0) input2 := produce(1) result := fanin(input1, input2) done := make(chan bool) go func() { for value := range result { fmt.Printf("got %d\n", value) } close(done) }() <-done fmt.Println("done") }
ここでは、Produce 関数を使用してさまざまなソースをシミュレートします。これらのソース チャネルは、結合操作を実行する fanin 関数に送信されます。
fanin 関数は出力チャネルを作成し、各入力で動作する goroutine を起動します。 WaitGroup を使用して、すべての入力ソースが出力チャンネルに結合されたことを示します。
この単純な例では、メインスレッドは出力を反復処理するだけです。順序には保証がなく、2 つの入力の値が混在していることに注意してください。
重要な点は、入力の結合が完了したら出力チャンネルを閉じる必要があるということです。チャンネルが空になると、範囲オペレーターは無期限に待機します。 close(output) 行をコメントアウトすると、デッドロック状態が発生していることがわかります。
これを改善するにはどうすればよいでしょうか?以下にコメントを残してください。
ありがとうございます!
この投稿とこのシリーズのすべての投稿のコードはここにあります
以上がGo のファニン パターンの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。