2016-10-04 10 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

Что делать, если я имитирую эту панику и сохраняю тип ошибки? Он должен быть таким же во время пробега, не так ли? –