2016-10-04 8 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은 채널이며 다른 goroutine으로 닫을 수 있습니다. 닫을 수있는 채널로 보낼 수있는 안전한 방법이 없으므로 여기서 당황 스러울 것입니다. 문제는 다른 패닉이 발생할 수 있으며 닫힌 chan으로 작성하여 발생하는 것에 반응하고 싶습니다.

Go에서이 작업을 수행 할 수 있습니까?

+0

일반적으로이를 감지하지 않아야하며 프로그램을 설계하는 다른 방법이 있습니다. 프로그램을 중단시키려는 공포감의 이유가 있습니다. – JimB

+0

TTL 캐시를 기반으로 제작되었습니다. 커넥터에서 미래를 만들려고 할 때 희박한 경쟁 조건이 있습니다. 만료되었고 캐시에서 제거되었습니다. SharedMutex를 추가하여 사물을 동기화 할 수 있지만 _potential_ RC를 해결하면서 일정한 런타임 비용 만 추가합니다. 공포감을 다루는 것은 나에게 합당한 해킹처럼 보입니다 –

+0

하지만 채널이 폐쇄되는 이유는 무엇입니까? 닫기는 발신자 (보통)가 보내는 신호이므로 채널이 닫힐 때 패닉 상태입니다. – JimB

답변

1

이 경우 복구 메시지는 런타임의 unexported 오류 값이며 문자열 값은 "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

이 패닉을 시뮬레이션 한 다음 오류 유형을 저장하면 어떻게됩니까? 그것은 달리기 동안 동일해야합니다, 그렇지 않아야합니까? –