2017-04-23 14 views
1

私は、文字列を受け取るチャンネルをとるゴルーチンのループを作ろうとしており、受信するたびにその値を別の文字列に追加する必要があります。すべてのgoroutinesの最後で(ゴルーチンのカウントは、渡されたlistの長さでなければなりません)、コードを続けてください。チャンネル受信機をとり、チャンネルに文字列を送るゴルーチン

以下の例では、strReceiverチャネルの値をstrに追加していないようです。strは変更されていないためです。

何が問題なのですか?

func appendToStr(str string, list []string, origin *url.URL) { 
    var currProc int32 = 0; 
    var maxProc int32 = int32(len(list)) 

    var strReceiver := make(chan string, len(list)) 
    for _, item := range list { 
     go func() { 
      doAsyncAndIncrement(item, strReceiver, &currProc) 
      str += <-strReceiver 
     }() 
    } 

    for { 
     if atomic.LoadInt32(&currProc) <= maxProc { 
      break; 
     } 
    } 

    // continue on using 'str' which now contains the append values from the 'strReceiver' channel 
} 

func doAsyncAndIncrement(item string, receiver chan<- string, count *int32) { 
    defer atomic.AddInt32(count, 1) 

    var val string 
    // do something with 'item' and set 'val'... 

    receiver <- val 
} 
+1

申し訳ありませんが、それは私の誤植です。非同期関数は本当にその受信機に入るべきです。コードを更新しました。 – Lansana

+0

'atomic.LoadInt32(&currProc)<= maxProc'この条件は否定してはいけませんか? currProcは、生成されたgoroutinesが実行するチャンスを取る前であっても、最初の繰り返しで中断します – nvartolomei

答えて

1

あなたのコードでの1つの問題は、あなたの定型呼び出しの閉鎖が大きすぎるということです。

for _, item := range list { 
    go func() { 
     doAsyncAndIncrement(item, strReceiver, &currProc) 
     str += <-strReceiver 
    }() 
} 

itemがあなたのゴルーチンのループのためではなく、無名関数にスコープされ、あなたはNのゴルーチンをオフに発射しながら、ので、あなたのitem変数は、一方のためのループで更新されています。これを修正するには、クロージャを使用しないように、変数を明示的にゴルーチンに渡します。

for _, item := range list { 
    go func(item string) { 
     doAsyncAndIncrement(item, strReceiver, &currProc) 
     str += <-strReceiver 
    }(item) 
}