Ответ
Для динамического 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 снижает читаемость и производительность. Используйте только когда действительно нужна динамичность, например, при построении обобщенных библиотек или фреймворков, где количество и тип каналов неизвестны заранее.