2016-04-02 7 views
0

以下は簡単な例です。私は、例を短くするために意図的にエラー処理などを省略しました。私は、関数を同時に実行させるために、goキーワードを使って5回writeOutput関数を呼び出す単純なforループを持っています。Golangは、並行処理の動作が期待通りに機能しないようにします。

テストの内容で/ tmp /に5つのファイルが作成されます。

ファイルが作成されないということが起こります。

ただし、goキーワードを削除すると、コードは期待通りに実行されます。私は何かを見過ごしています。私の背景は、PHP/Rubyのような動的に型付けされた言語なので、やりとりするだけで、goキーワードが存在すると5つのファイルが作成される理由を理解できません。

package main 

import (
    "os" 
    "math/rand" 
    "strconv" 
) 

func main() { 

    for i := 0; i < 5; i++ { 
    go writeOutput() 
    } 

} 

func writeOutput() { 
    filename := strconv.Itoa(rand.Intn(10000)) 
    file, _ := os.Create("/tmp/" + filename) 
    defer file.Close() 
    file.WriteString("test") 
} 
+3

main関数は、スケジューラが 'writeOutput'のいずれかのゴルーチンを実行する時間を待つ前に戻っています。 'sync.WaitGroup'を使ってすべてのゴルーチンが終了するまで待ちます。 –

+0

@TimCooper私はあなたの提案を使用して問題を解決するために助けてくれてありがとう。私がその事例を改善できると思ったら教えてください。 –

答えて

4

私はコメントで示唆されているように、これを待機グループで解決することができました。

package main 

import (
    "math/rand" 
    "os" 
    "strconv" 
    "sync" 
) 

func main() { 

    var wg sync.WaitGroup 

    for i := 0; i < 5; i++ { 
     wg.Add(1) 
     go func() { 
      defer wg.Done() 
      writeOutput() 
     }() 
    } 
    wg.Wait() 

} 

func writeOutput() { 
    filename := strconv.Itoa(rand.Intn(10000)) 
    file, _ := os.Create("/tmp/" + filename) 
    defer file.Close() 
    file.WriteString("test") 
} 
+0

ありがとう私はあなたの例を答えとして使用しているので、コードがより柔軟になります。 –

+3

これはほぼ正しいですが、パニックの場合、wg.Done()は呼び出されず、プログラムはデッドロックでクラッシュします。これを修正するには、gouroutineの最初の文として 'defer wg.Done()'を呼び出します。 –

+1

また、慌てないでください。エラーがないかどうかをチェックして早期に返す。 – voutasaurus

関連する問題