1

私は再帰関数を持っています。関数は、取得するデータに応じてさまざまな値で自分自身を呼び出すため、再帰のアリティと深さは不明です。各呼び出しは、自分自身を 0 回以上呼び出す可能性があります。この関数は、任意の数の値を返すことができます。

ゴルーチンとチャネルを関与させて並列化したいと考えています。の各再帰はinner独自のゴルーチンで実行され、チャネルで値を返します。外側の関数は、これらの値を処理します。

func outer(response []int) {

  results := make([]int)
  resultsChannel := make(chan int)

  inner := func(...) {
      resultsChannel <- «some result»;

      // Recurse in a new goroutine.
      for _, recursionArgument in «some calculated data» {
          go inner(recursionArgument)
      }
  }

  go inner(«initial values»);

  for {
      result := <- resultsChannel
      results = append(results, result)

      // HELP! How do I decide when to break?
  }

  return results
}

この問題は、結果チャネル ループをエスケープするときに発生します。再帰の「形」(不明なアリティと深さ) のため、「n 個のイベント後に終了する」とは言えず、センチネル値を送信することもできません。

すべての再帰が発生して から戻るタイミングを検出するにはどうすればよいouterですか? これにアプローチするより良い方法はありますか?

4

1 に答える 1

3

を使用して、sync.WaitGroupスポーンするゴルーチンのコレクションを管理できます。Add(1)新しい各ゴルーチンをスポーンする前、およびDone各ゴルーチンが完了するときに呼び出します。だから、このようなもの:

var wg sync.WaitGroup
inner := func(...) {
    ...
    // Recurse in a new goroutine.
    for _, recursionArgument := range «some calculated data» {
          wg.Add(1)
          go inner(recursionArgument)
    }
    ...
    wg.Done()
}
wg.Add(1)
go inner(«initial values»)

待っているwgと、すべてのゴルーチンがいつ完了するかがわかります。

チャネルから結果を読み取っている場合、結果がなくなったことを確認する明白な方法は、チャネルを閉じることです。これを行う別のゴルーチンを使用して、これを実現できます。

go func() {
    wg.Wait()
    close(resultsChannel)
}()

rangeこれで、単純にresultsChannelすべての結果を読み取ることができるはずです。

于 2013-12-03T14:53:14.650 に答える