2013-05-16 4 views
9

は、簡略化した例として、以下のコードを検討:ガベージコレクタは続行されないGoルーチンを収集しますか?

func printer(c <-chan int) { 
    for { 
     fmt.Print(<-c) 
    } 
} 

func provide() { 
    c := make(chan int) 

    go printer(c) 

    for i := 1; i <= 100; i++ { 
     c <- i 
    } 
} 

機能provideprovideが生成するデータを印刷することprinterルーチン行くを作成します。

私の質問は、provideが返ってから何が起こり、printerが空のチャンネルでブロックを開始するかです。 cへの参照がないか、またはガベージコレクタがこのケースをキャッチし、goルーチンとcの両方を処分しますか?

この種のコードでメモリリークが発生する場合は、そのようなメモリリークを防ぐためにどのような対策を講ずることができますか?

答えて

10

チャンネルを閉じます。閉じたチャンネルからの読み取りは常に成功し、それぞれのゼロ値を返します。オプションの2番目のboolean戻り値は、最初の値の妥当性を示します。

Receive operator

Aは

x, ok = <-ch 
x, ok := <-ch 
var x, ok = <-ch 

は、通信が成功したかどうかを報告タイプboolの追加の結果をもたらす形の割当てまたは初期化で使用される表現を受け取ります。 okの値は、受信した値がチャネルに正常に送信された場合にtrue、チャネルが閉じられて空であるために生成されたゼロ値であればfalseです。

func printer(c <-chan int) { 
     for { 
       v, ok := <-c 
       if !ok { // chan closed 
         return 
       } 

       // v is valid 
       fmt.Println(v) 
     } 
} 

func provide() { 
     c := make(chan int) 

     go printer(c) 

     for i := 1; i <= 100; i++ { 
       c <- i 
     } 
     close(c) 
} 
+1

ありがとうございます。明らかに私の "解決策"は本当にうまくいかなかった。 – fuz

+3

プリンタのゴルーチンの範囲句を使用すると、v:= range c {fmt.Println(v)}のokチェックを避けることができます。 – Philipp

+0

@Philipp:うん、そうです。 – zzzz

0

次のプログラムを試して、実際にメモリがリークすることを確認してください。このプログラムはあなたのRAMをかなり早く食べることに注意してください。それを殺すために準備してください。

package main 

func worker(c <-chan int) { 
    var i int 

    for { 
     i += <-c 
    } 
} 

func wrapper() { 
    c := make(chan int) 

    go worker(c) 

    for i := 0; i < 0xff; i++ { 
     c <- i 
    } 
} 

func main() { 
    for { 
     wrapper() 
    } 
} 

このリークを解決するには、現在孤立しているゴールーチンによって参照されているチャネルを閉じます。ランタイムは、閉じられたチャネルのみからのGoルーチンの読取りは、決して続かず、解放することに気づいています。固定コードは次のようになります。

package main 

func worker(c <-chan int) { 
    var i int 

    for { 
     i += <-c 
    } 
} 

func wrapper() { 
    c := make(chan int) 
    defer close(c) // fix here 

    go worker(c) 

    for i := 0; i < 0xff; i++ { 
     c <- i 
    } 
} 

func main() { 
    for { 
     wrapper() 
    } 
} 
関連する問題