Ответ
Для динамического select можно использовать reflect.Select. Он позволяет создавать case-ы во время выполнения. Пример:
cases := make([]reflect.SelectCase, 0)
// Добавляем case для канала
ch := make(chan int)
cases = append(cases, reflect.SelectCase{
Dir: reflect.SelectRecv,
Chan: reflect.ValueOf(ch),
})
// Добавляем case с default
cases = append(cases, reflect.SelectCase{
Dir: reflect.SelectDefault,
})
// Выполняем select
chosen, recv, recvOK := reflect.Select(cases)
// Обработка результата
switch chosen {
case 0:
if recvOK {
fmt.Printf("Получено: %vn", recv.Interface())
} else {
fmt.Println("Канал закрыт")
}
case 1:
fmt.Println("Default case сработал")
}Ключевые моменты:
reflect.SelectCaseописывает каждый case.Dirуказывает направление:reflect.SelectRecv(получение),reflect.SelectSend(отправка) илиreflect.SelectDefault(default-ветка).Chanдолжно бытьreflect.ValueOfканала.Send(для отправки) иRecv(для получения) должны бытьreflect.ValueOfзначений.- Можно динамически добавлять/удалять case-ы в слайсе
cases. reflect.Selectвозвращает индекс выбранного case (chosen), полученное/отправленное значение (recv) и булево значениеrecvOK(для получения).
Осторожно: reflection снижает читаемость и производительность. Используйте только когда действительно нужна динамичность, например, при построении обобщенных библиотек или фреймворков, где количество и тип каналов неизвестны заранее.