Обычно, когда вы используете блокирующий канал и функцию тайм-аута, вы можете поместить его в поле выбора l oop.
ctx, cancel := context.WithTimeout(req.Context(), 5000*time.Second)
// Wait for the response or timeout
for {
select {
case <-ctx.Done():
log.Println("timeout, cancel work...")
// Cancel the request and wait for it to complete
// this will shutdown the go-routine immediately
tr.CancelRequest(req)
log.Println(<-ch)
break
case err := <-ch:
// do something
break
}
}
В этом случае <-ch
больше не блокирует и избранный вызывает ctx.Done()
более одного раза. Если вы не используете for-l oop, ctx.Done()
вызывается только один раз (как уже указывал @icza)