Справочная информация:
Я использую собственный LDAP-сервер пакет . Он использует Done
канал в запросах, чтобы сообщить обработчику, если - скажем, клиент отключается - и, следовательно, обработчик должен также прервать работу. Например, .
Поскольку канал Done
является старым способом обработки отмены - и мое желание поддерживать цепочку отмены - я создал context.Context
для этого канала следующим образом:
func doneContext(p context.Context, done <-chan bool) (
ctx context.Context, cancel context.CancelFunc,
) {
ctx, cancel = context.WithCancel(p)
go func() {
<-done
cancel() // done closed, so cancel our context
}()
return
}
Предполагалось, что канал done
будет закрыт для обоих:
- отключений клиента; и
- успешных обработчиков (которые полностью выполняются)
Первое подтвердилось, второе - нет. Успешные вызовы обработчика , а не приводят к закрытию канала done
, и, таким образом, я пропускаю подпрограммы.
Чтобы решить эту проблему - и так как я отменял свой собственныйcontext.Context
при завершении обработчика - успешно или нет, например,
// convert the client request's Done channel into a context.Context
ctx, cancel := doneContext(context.Background(), m.Done)
defer cancel() // clean-up context: rain or shine
Я обновил процедуру запуска doneContext
следующим образом:
go func() {
select {
case <-done:
cancel() // done closed, so cancel our context (like before)
case <-ctx.Done():
// when our context is canceled, recover the go-routine (even if done never closes)
}
}()
Вопросы:
- - это правильный путь для обновления канала
done
старого стиля в более современный context.Context
- , если я обеспокоен тем, что внешний пакетЯ использую, не закрывая канал
done
? - т.е. будет ли
GC
собирать этот канал, даже если он никогда не закрыт?