日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > php >内容正文

php

php7.0 yield,PHP7中生成器的新特性 yield-from amp;amp; return-values

發布時間:2023/12/15 php 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 php7.0 yield,PHP7中生成器的新特性 yield-from amp;amp; return-values 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

生成器委托

簡單地翻譯官方文檔的描述:

PHP7中,通過生成器委托(yield from),可以將其他生成器、可迭代的對象、數組委托給外層生成器。外層的生成器會先順序 yield 委托出來的值,然后繼續 yield 本身中定義的值。

利用 yield from 可以方便我們編寫比較清晰生成器嵌套,而代碼嵌套調用是編寫復雜系統所必需的。

上例子:

function echoTimes($msg, $max) {

for ($i = 1; $i <= $max; ++$i) {

echo "$msg iteration $i\n";

yield;

}

}

function task() {

yield from echoTimes('foo', 10); // print foo ten times

echo "---\n";

yield from echoTimes('bar', 5); // print bar five times

}

foreach (task() as $item) {

;

}

以上將輸出:

foo iteration 1

foo iteration 2

foo iteration 3

foo iteration 4

foo iteration 5

foo iteration 6

foo iteration 7

foo iteration 8

foo iteration 9

foo iteration 10

---

bar iteration 1

bar iteration 2

bar iteration 3

bar iteration 4

bar iteration 5

自然,內部生成器也可以接受它的父生成器發送的信息或者異常,因為 yield from 為父子生成器建立一個雙向的通道。不多說,上例子:

function echoMsg($msg) {

while (true) {

$i = yield;

if($i === null){

break;

}

if(!is_numeric($i)){

throw new Exception("Hoo! must give me a number");

}

echo "$msg iteration $i\n";

}

}

function task2() {

yield from echoMsg('foo');

echo "---\n";

yield from echoMsg('bar');

}

$gen = task2();

foreach (range(1,10) as $num) {

$gen->send($num);

}

$gen->send(null);

foreach (range(1,5) as $num) {

$gen->send($num);

}

//$gen->send("hello world"); //try it ,gay

輸出和上個例子是一樣的。

生成器返回值

如果生成器被迭代完成,或者運行到 return 關鍵字,是會給這個生成器返回值的。

可以有兩種方法獲取這個返回值:

使用 $ret = Generator::getReturn() 方法。

使用 $ret = yield from Generator() 表達式。

上例子:

function echoTimes($msg, $max) {

for ($i = 1; $i <= $max; ++$i) {

echo "$msg iteration $i\n";

yield;

}

return "$msg the end value : $i\n";

}

function task() {

$end = yield from echoTimes('foo', 10);

echo $end;

$gen = echoTimes('bar', 5);

yield from $gen;

echo $gen->getReturn();

}

foreach (task() as $item) {

;

}

輸出結果就不貼了,想必大家都猜到。

可以看到 yield from 和 return 結合使得 yield 的寫法更像平時我們寫的同步模式的代碼了,畢竟,這就是 PHP 出生成器特性的原因之一呀。

一個非阻塞的web服務器

時間回到2015年,鳥哥博客上轉載的一篇《 在PHP中使用協程實現多任務調度》。文章介紹了PHP5 的迭代生成器,協程,并實現了一個簡單的非阻塞 web 服務器。(鏈接見文末引用)

現在我們利用 PHP7 中的這兩個新特性重寫這個 web 服務器,只需要 100 多行代碼。

代碼如下:

class CoSocket

{

protected $masterCoSocket = null;

public $socket;

protected $handleCallback;

public $streamPoolRead = [];

public $streamPoolWrite = [];

public function __construct($socket, CoSocket $master = null)

{

$this->socket = $socket;

$this->masterCoSocket = $master ?? $this;

}

public function accept()

{

$isSelect = yield from $this->onRead();

$acceptS = null;

if ($isSelect && $as = stream_socket_accept($this->socket, 0)) {

$acceptS = new CoSocket($as, $this);

}

return $acceptS;

}

public function read($size)

{

yield from $this->onRead();

yield ($data = fread($this->socket, $size));

return $data;

}

public function write($string)

{

yield from $this->onWriter();

yield fwrite($this->socket, $string);

}

public function close()

{

unset($this->masterCoSocket->streamPoolRead[(int)$this->socket]);

unset($this->masterCoSocket->streamPoolWrite[(int)$this->socket]);

yield ($success = @fclose($this->socket));

return $success;

}

public function onRead($timeout = null)

{

$this->masterCoSocket->streamPoolRead[(int)$this->socket] = $this->socket;

$pool = $this->masterCoSocket->streamPoolRead;

$rSocks = [];

$wSocks = $eSocks = null;

foreach ($pool as $item) {

$rSocks[] = $item;

}

yield ($num = stream_select($rSocks, $wSocks, $eSocks, $timeout));

return $num;

}

public function onWriter($timeout = null)

{

$this->masterCoSocket->streamPoolWrite[(int)$this->socket] = $this->socket;

$pool = $this->masterCoSocket->streamPoolRead;

$wSocks = [];

$rSocks = $eSocks = null;

foreach ($pool as $item) {

$wSocks[] = $item;

}

yield ($num = stream_select($rSocks, $wSocks, $eSocks, $timeout));

return $num;

}

public function onRequest()

{

/** @var self $socket */

$socket = yield from $this->accept();

if (empty($socket)) {

return false;

}

$data = yield from $socket->read(8192);

$response = call_user_func($this->handleCallback, $data);

yield from $socket->write($response);

return yield from $socket->close();

}

public static function start($port, callable $callback)

{

echo "Starting server at port $port...\n";

$socket = @stream_socket_server("tcp://0.0.0.0:$port", $errNo, $errStr);

if (!$socket) throw new Exception($errStr, $errNo);

stream_set_blocking($socket, 0);

$coSocket = new self($socket);

$coSocket->handleCallback = $callback;

function gen($coSocket)

{

/** @var self $coSocket */

while (true) yield from $coSocket->onRequest();

}

foreach (gen($coSocket) as $item){};

}

}

CoSocket::start(8000, function ($data) {

$response = <<

HTTP/1.1 200 OK

Content-Type: text/plain

Content-Length: 12

Connection: close

hello world!

RES;

return $response;

});

參考資料

總結

以上是生活随笔為你收集整理的php7.0 yield,PHP7中生成器的新特性 yield-from amp;amp; return-values的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。