Функция reflect.Select
Функция reflect.Select выполняет выбор из набора каналов,
аналогично оператору select в Go, но в рефлексии.
Она принимает слайс из структуры reflect.SelectCase,
которая описывает каждую операцию над каналом. Функция возвращает индекс
выбранного случая, значение, полученное из канала (если это операция приема),
и флаг, указывающий, было ли значение получено успешно.
Эта функция является ключевым инструментом для динамической работы с каналами,
когда структура операций выбора заранее неизвестна.
Синтаксис
reflect.Select(cases []reflect.SelectCase) (chosen int, recv reflect.Value, recvOK bool)
Структура reflect.SelectCase
Структура reflect.SelectCase описывает один случай в операторе
выбора. Она содержит три поля:
-
Dir- направление операции:reflect.SelectSend(отправка),reflect.SelectRecv(прием) илиreflect.SelectDefault(по умолчанию); -
Chan- значение типаreflect.Value, представляющее канал; -
Send- значение для отправки, если операция отправки.
Пример 1: Блокирующий выбор
Давайте создадим два канала и выполним блокирующий выбор между ними:
package main
import (
"fmt"
"reflect"
"time"
)
func main() {
ch1 := make(chan string)
ch2 := make(chan string)
go func() {
time.Sleep(100 * time.Millisecond)
ch1 <- "from channel 1"
}()
go func() {
time.Sleep(50 * time.Millisecond)
ch2 <- "from channel 2"
}()
cases := []reflect.SelectCase{
{
Dir: reflect.SelectRecv,
Chan: reflect.ValueOf(ch1),
},
{
Dir: reflect.SelectRecv,
Chan: reflect.ValueOf(ch2),
},
}
chosen, recv, recvOK := reflect.Select(cases)
fmt.Printf("chosen: %d, recv: %s, recvOK: %t", chosen, recv.String(), recvOK)
}
Результат выполнения кода:
"chosen: 1, recv: from channel 2, recvOK: true"
Пример 2: Отправка данных в канал
Давайте выполним операцию отправки данных в канал:
package main
import (
"fmt"
"reflect"
)
func main() {
ch := make(chan int, 1)
cases := []reflect.SelectCase{
{
Dir: reflect.SelectSend,
Chan: reflect.ValueOf(ch),
Send: reflect.ValueOf(12345),
},
}
chosen, recv, recvOK := reflect.Select(cases)
fmt.Printf("chosen: %d, recv: %s, recvOK: %t", chosen, recv.String(), recvOK)
}
Результат выполнения кода:
"chosen: 0, recv: <invalid Value>, recvOK: false"
Пример 3: Неблокирующий выбор с default
Давайте используем операцию по умолчанию для неблокирующего выбора:
package main
import (
"fmt"
"reflect"
)
func main() {
ch := make(chan int)
cases := []reflect.SelectCase{
{
Dir: reflect.SelectRecv,
Chan: reflect.ValueOf(ch),
},
{
Dir: reflect.SelectDefault,
},
}
chosen, recv, recvOK := reflect.Select(cases)
fmt.Printf("chosen: %d, recv: %s, recvOK: %t", chosen, recv.String(), recvOK)
}
Результат выполнения кода:
"chosen: 1, recv: <invalid Value>, recvOK: false"
Смотрите также
-
функцию
reflect.MakeChan,
которая создает канал в рефлексии -
функцию
reflect.ValueOf,
которая возвращает значение как объект рефлексии -
функцию
reflect.TypeOf,
которая возвращает тип значения в рефлексии -
функцию
reflect.DeepEqual,
которая выполняет глубокое сравнение значений