Классический паттерн таймаута через select:
// Простой таймаут для одной операции
select {
case msg := <-ch:
fmt.Println("received:", msg)
case <-time.After(3 * time.Second):
fmt.Println("timeout!")
}
// Для цикла лучше использовать context:
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()
for {
select {
case msg := <-ch:
process(msg)
case <-ctx.Done():
fmt.Println("deadline exceeded")
return
}
}
Важно: time.After в цикле select создает новый таймер на каждой итерации (утечка памяти). Для одноразового таймаута - подходит. Для цикла - используйте context.WithTimeout или time.NewTimer с Reset().