## Select >[danger] 由于 Swoole 4.4 无法识别死锁,大量使用 Select 风险较高,建议等 Swoole 5 解决死锁问题后使用 > select 是 Go 中的一个控制结构,类似于用于通信的 switch 语句。每个 case 必须是一个通信操作,要么是发送要么是接收,select 随机执行一个可运行的 case。如果没有 case 可运行,它将阻塞,直到有 case 可运行。一个默认的子句应该总是可运行的。 select 是 Go 语言的一种语法,主要用在: - 同一个协程处理多个 Channel 的消息 - 当 Channel 满/空时执行默认操作:丢弃消息 由于 Swoole 缺少该语法,于是 Mix 率先自行研发了该项功能,与 Go 版本功能完全一致。 ## 函数版本 - 常规使用 ~~~ $c1 = new \Mix\Coroutine\Channel(); $c2 = new \Mix\Coroutine\Channel(); select( select_case(Select::pop($c1), function ($value) { var_dump($value); }), select_case(Select::pop($c2), function ($value) { var_dump($value); }), select_default(function () { var_dump('default'); }) )->run(); ~~~ - 跳出循环 ~~~ use Mix\Time\Time; $c1 = new \Mix\Coroutine\Channel(); $timer = Time::newTimer(1 * Time::MILLISECOND); for ($i = 0; $i < 10; $i++) { if (select( select_case(select_pop($c1), function ($value) { var_dump($value); }), select_case(select_pop($timer->channel()), function ($value) { return SELECT_BREAK; }) ))->run()->break()) { break; // or return } } ~~~ - 通道满,丢弃数据 ~~~ $c1 = new \Mix\Coroutine\Channel(); select( select_case(select_push($c1, 'message'), function ($value) { }), select_default(function () { // 当 c1 满时执行这里,等于丢弃消息 }) ))->run(); ~~~ ## Class 版本 - 常规使用 ~~~ use Mix\Select\Select; $c1 = new \Mix\Coroutine\Channel(); $c2 = new \Mix\Coroutine\Channel(); (new Select( Select::case(Select::pop($c1), function ($value) { var_dump($value); }), Select::case(Select::pop($c2), function ($value) { var_dump($value); }), Select::default(function () { var_dump('default'); }) ))->run(); ~~~ - 跳出循环 ~~~ use Mix\Select\Select; use Mix\Time\Time; $c1 = new \Mix\Coroutine\Channel(); $timer = Time::newTimer(1 * Time::MILLISECOND); for ($i = 0; $i < 10; $i++) { if ((new Select( Select::case(Select::pop($c1), function ($value) { var_dump($value); }), Select::case(Select::pop($timer->channel()), function ($value) { return Select::BREAK; }) ))->run()->break()) { break; // or return } } ~~~ - 通道满,丢弃数据 ~~~ use Mix\Select\Select; $c1 = new \Mix\Coroutine\Channel(); (new Select( Select::case(Select::push($c1, 'message'), function ($value) { }), Select::default(function () { // 当 c1 满时执行这里,等于丢弃消息 }) ))->run(); ~~~