生成器(Generator)使用详解
生成器是 PHP 5.5+ 引入的特性,用于高效处理大数据集,避免内存溢出。
基本语法
使用 yield 关键字创建生成器:
php
function rangeGenerator($start, $end) {
for ($i = $start; $i <= $end; $i++) {
yield $i;
}
}
// 使用
foreach (rangeGenerator(1, 1000000) as $number) {
echo $number . "\n";
}对比内存占用
php
// ❌ 内存占用高
$numbers = range(1, 1000000); // 约 134MB
foreach ($numbers as $n) {
// ...
}
// ✅ 生成器几乎不占内存
function bigRange($start, $end) {
for ($i = $start; $i <= $end; $i++) {
yield $i;
}
}
foreach (bigRange(1, 1000000) as $n) {
// 仅占用几KB
}生成键值对
php
function keyValueGenerator() {
yield 'id' => 1;
yield 'name' => '张三';
yield 'age' => 25;
}
foreach (keyValueGenerator() as $key => $value) {
echo "$key: $value\n";
}从生成器获取值
php
function gen() {
yield 1;
yield 2;
yield 3;
}
$generator = gen();
echo $generator->current(); // 1
$generator->next();
echo $generator->current(); // 2
// 或使用 foreach
foreach ($generator as $value) {
echo $value;
}双向通信(PHP 7+)
php
function printer() {
while (true) {
$line = yield;
echo "收到: $line\n";
}
}
$printer = printer();
$printer->send("Hello"); // 收到: Hello
$printer->send("World"); // 收到: World读取大文件
php
function readLargeFile($filename) {
$handle = fopen($filename, 'r');
while (!feof($handle)) {
yield fgets($handle);
}
fclose($handle);
}
// 处理 GB 级文件只需几 MB 内存
foreach (readLargeFile('huge.log') as $line) {
processLine($line);
}yield from(PHP 7+)
委托给另一个生成器:
php
function subGenerator() {
yield 1;
yield 2;
}
function mainGenerator() {
yield 'a';
yield from subGenerator();
yield 'b';
}
// 输出: a, 1, 2, b
foreach (mainGenerator() as $value) {
echo $value;
}注意事项
- 生成器不能
return值(PHP 7 起可以return) - 生成器是单向的,不能倒退
- 生成器对象不能被序列化