2016-10-04 7 views
0
を取得

コードあります:ゴラン。パニックタイプ

func (c *Connector) SendPacketFuture(p []byte) (future chan []byte) { 
    defer func() { 
     // TODO Check r to catch only chan panics 
     if r := recover(); r != nil { 
      future = nil 
     } 
    }() 
    t := newConnectorTask(p) 
    c.tasks <- t 
    future = t.PacketFromServerChan 
    return 
} 

TODOはかなり自明です。 c.tasksはチャネルであり、別のゴルーチンによって閉じられます。閉鎖できるチャンネルに安全に送る方法はないので、私はここでパニックを起こしています。問題はさまざまなパニックが発生する可能性があることです。閉鎖されたchanに書き込むことによって引き起こされるものに反応したい

Goでこれを行うことはできますか?

+0

一般的に、これを検出しようとするべきではありません。また、プログラムを設計する別の方法があります。プログラムがクラッシュする恐れがある理由があります。 – JimB

+0

TTLキャッシュを中心に構築されています。まれな競合状態です。コネクタを使用して未来を作成しようとしたときに、期限切れになってキャッシュから削除されました。私はSharedMutexを追加して物事を同期することができますが、これは_Potential_RCを解決しながら一定のランタイムコストを追加するだけです。パニックに対処することは合理的なハックだと思われる –

+0

しかし、なぜチャネルは閉じられていますか?クローズは、送信者(通常)が送信する信号であり、したがって、チャネルが閉じられるとパニックが発生します。 – JimB

答えて

1

この場合の回復メッセージは、実行時のエラーが報告されていないエラー値で、文字列値は"send on closed channel"です。実際に

if e, ok := r.(error); ok && w.Error() == "send on closed channel" { 
    fmt.Println("recover from send on closed channel") 
} 

https://play.golang.org/p/LNcfdE9Bg2

、あなたはおそらく終了したときに合図するために、別のチャネルで必要なもの:あなたがここに行うことができます

唯一のものは、エラー文字列を一致させることです。

t := newConnectorTask(p) 

select { 
case <-c.close: 
    // closing the c.close channel will unblock this case 
    return 
case c.tasks <- t: 
} 
+0

ああ、これはうまくいくはずです。ありがとうございます –

+0

@ViacheslavKroilov:変更する可能性は低いですが、Goの将来のバージョンでも動作し続ける保証はなく、エラー値が指定されていないため、他のGo実装でも動作するという保証はありません。 – JimB

+0

このパニックをシミュレートしてエラータイプを保存するとどうなりますか?それは実行の間に同じでなければならないでしょうか? –