2017-12-04 7 views
1

私は2つのio.ReadWriterの間でメッセージを転送するために使用される関数を持っています。エラーが発生すると、エラーをログに記録してリターンする必要があります。しかし、私は私のコードでゴルーチン漏れの問題を抱えているかもしれないと思う:2つの入力を持つ出力を1つしか持たないバッファを1つ持つチャンネルで、ゴルーチン漏れが起こりますか?

func transport(rw1, rw2 io.ReadWriter) error { 
    errc := make(chan error, 1) // only one buffer 
    go func() { 
     _, err := io.Copy(rw1, rw2) 
     errc <- err 
    }() 

    go func() { 
     _, err := io.Copy(rw2, rw1) 
     errc <- err 
    }() 

    err := <-errc // only one error catched 
    if err != nil && err == io.EOF { 
     err = nil 
    } 
    return err 
} 

唯一つのエラーがこの機能に巻き込まれる可能があるので、二ゴルーチンの終了し、通常化け?または別のエラーを受け取るためにもう一度err <- errcと書いてください。

答えて

3

1つのゴルーチンからの値が受信され、もう一方がバッファされます。どちらのゴルーチンもチャンネルに送信して終了できます。漏れはありません。

送信する最初のゴルーチンが成功し、2番目のゴルーチンにエラーが発生したときにアプリケーションがエラーを検出するようにするには、両方の値を受け取ると便利です。

var err error 
for i := 0; i < 2; i++ { 
    if e := <-errc; e != nil { 
    err = e 
    } 
} 

io.Copyがio.EOFを返さないので、エラーを収集する際にio.EOFをチェックする必要はありません。

errc := make(chan error, 1) 
go func() { 
    _, err := io.Copy(rw1, rw2) 
    errc <- err 
}() 

_, err := io.Copy(rw2, rw1) 

if e := <-errc; e != nil { 
    err = e 
} 
+0

おかげで、スリーズ:

コードは、単一のゴルーチンを使用するように簡略化することができます。 'errc'が2回設定されるようにサイズ2のチャンネルを設定すればもう1つの質問がありますが、' funcトランスポート 'は一度だけ読み込んで終了します。 – vinllen

+0

はい、容量2のチャンネルを使用してリークを防ぐことができます。 –

+0

ありがとうございます!それは私を助ける – vinllen

関連する問題