2017-10-06 7 views
-2

複数の機能を並列に実行する必要があります。
関数がtrue(チャネルにtrueを送信する)を返す場合でも、最終結果はtrueである必要があります。ゴランのチャンネルにつきました

これを達成するにはどうすればよいのですか?

// Some performance intensive function 
func foo(i int, c chan bool) { 
    // do some processing and return either true or false 
    c <- true // or false 
} 

func main() { 
    flg := false 
    ch := make(chan bool) 
    for i := 0; i < 10; i++ { 
     go foo(i, ch) 
    } 
    // If even once foo() returned true then val should be true 
    flg = flg || <-ch 
} 
+0

「チャンネルを使用してこれを達成するにはどうすればよいですか? ---あなたはそれのためのチャネルを使用する必要があります何らかの理由は? – zerkms

+1

お試しください。あなたのコードはチャンネルをまったく使用しません。 – Flimzy

+0

(あなたのコードは書かれているように読みにくいので、 'gofmt'を使うことをお勧めします) – Flimzy

答えて

0

あなただけ(foo()呼び出しのいずれかによって送信された値になり、多くの予測不可能なもの)チャンネルから一つの値を受け取りますしかし、あなたはすべてを受け取りたい。あなたはそれを(送信)され送るよう

ように多くの値を受け取るためにforループを使用します。

for i := 0; i < 10; i++ { 
    flg = flg || <-ch 
} 

1つのtrue値が受信されるまで、あなたの場合には、それがループに十分だろうが、その意志としてflgの最終的な値を決定してください。残りのすべての値を受け取ることをお勧めします(chはバッファされていないチャンネルです)。この例では重要ではありませんが、「実生活」アプリケーションでは、ゴルーチンが永遠に(メモリリーク)発生します。

あなたはとてもすべてのゴルーチンが、上の値を送信することができ、オプションはchをバッファリングすることです、(できるだけ早く1つのtrue値が検出されたとして)できるだけ早く完了し、返すために、すべてのfoo()の呼び出しを待つしたくない場合それはブロックされることなく。そして、あなたが(を待つようにと)を受信するために必要とされていないこの方法は、すべてのfoo()呼び出しが完了するまでに:

ch := make(chan bool, 10) 
for i := 0; i < 10; i++ { 
    go foo(i, ch) 
} 

flg := false 
for i := 0; i < 10; i++ { 
    if <-ch { 
     flg = true 
     break 
    } 
} 

は、このアプローチを選択するには、仕事はもはや不要なCPUを避けるために必要とされるゴルーチンをキャンセルするための手段を提供する必要があります(およびメモリ)の使用方法について説明します。 context.Contextはそれほど意味がありません。詳しくは、Close multiple goroutine if an error occurs in one in goをご覧ください。

1

あなたは、チャネルchから読み始めると、あなたは真の結果を得ればtrueflgを設定することができます。このように:

//flg = flg || <- ch 
for res := range ch { 
    if res { 
     flg = true 
    } 
} 

この方法で動作しますが、1つの重大な欠点を持っている - forループは無限のチャネルから新しい値を待ちます。ループを停止する慣習的な方法は、チャネルを閉じることです。あなたはそうすることができます:すべてのgoroutinesが終了するまで待つ別のゴルーチンを実行します。 Goはそれを行うための非常に便利なツールを提供します - sync.WaitGroup

ので、すべてのゴルーチンがそれにアクセスできるグローバルスコープでそれを定義します。

var (
    wg sync.WaitGroup 
) 

次にあなたがグループを待つためにもう一つのゴルーチンを追加ゴルーチンあなたが起動するたび:

for i := 0; i < 10; i++ { 
    wg.Add(1) // here 
    go foo(i, ch) 
} 

ゴルーチン仕上げをそれをマークする方法はwg.Doneです。

func foo(i int, c chan bool) { 
    //do some processing and return either true or false 
    c <- true //or false 
    wg.Done() // here 
} 

sepatate goroutineは、すべてのfoo goroutinesが終了してチャンネルを閉じるまで待機します。 wg.Waitブロック全てが終了するまで:

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

すべて一緒:https://play.golang.org/p/8qiuA29-jv

関連する問題