Реализуйте ProcessPriority. Она читает значения из двух каналов: high (важные) и low (обычные) и возвращает срез всех прочитанных значений в порядке обработки. Важные значения должны по возможности обрабатываться раньше обычных.
func ProcessPriority(high, low <-chan int) []int
Алгоритм на каждой итерации цикла:
- Неблокирующая попытка прочитать
high (select с default). Если значение есть, добавить его в результат и перейти к следующей итерации.
- Если
high сейчас пуст, дождаться любого из двух каналов обычным блокирующим select.
- Закрытый канал исключается из дальнейшего выбора. Функция завершается, когда закрыты оба.
Пример. Оба канала заранее заполнены и закрыты:
high := make(chan int, 3)
low := make(chan int, 2)
high <- 1; high <- 2; high <- 3
low <- 100; low <- 101
close(high); close(low)
fmt.Println(ProcessPriority(high, low)) // [1 2 3 100 101]
Что гарантируется, а что нет:
- Все значения из обоих каналов попадают в результат, если входы конечны.
- Если
high непрерывно готов, он обрабатывается раньше low. Это предпочтение первой проверки. Во втором блокирующем select выбор между готовыми каналами случаен.
- Строгой защиты
low от голодания нет: если high бесконечно и всегда готов, до low дело может не дойти. Для конечных входов задача завершается всегда.
Тесты проверяют полноту результата и сохранение порядка внутри каждого канала, точный порядок на предзаполненных закрытых каналах (весь high, затем low), обработку low, пока high открыт и пуст, случай с одним лишь low и завершение на конечных потоках. Защиту low от голодания при бесконечном high тесты не проверяют: алгоритм её и не обещает.