Во-первых, лучше контекст все же брать не Background, а из http-запроса. Таким образом вы будете корректно обрабатывать ситуацию, когда соединение с клиентом разорвалось и не надо больше обрабатывать запрос (контекст отменится).
ctx, cancel := context.WithTimeout(r.Context(), config.Read().HTTP.Timeout.Request*time.Second)
Во-вторых, контекст обычно не используют для ожидания внутренних горутин, он не для этого предназначен. Для этого используют
sync.WaitGroup
.
Поэтому у вас и возникает проблема, ибо событие отмены контекста еще не значит, что дочерние функции мгновенно завершились. Возникает ситуация, когда чтение канала
<-ctx.Done()
внутри приведенной вами функции происходит раньше, чем такое же чтение канала внутри функции router.middlewareHandler(h). Поэтому нужно ждать не отмены контекста, а завершения работы горутины.
В-третьих, вам тут вообще не нужна горутина, ибо ожидание ее завершения вы сделали сразу после нее. Вместо этого можно просто написать последовательный код.
В-четвертых, вы, наверное, хотели написать
if ctx.Err() != nil {
. Но у вас вместо этого ==, что вообще обесценивает код внутри этого ифа.