PHP 8.1 引入了never
返回类型,它是什么?never
和和有什么区别void
?
2 回答
never
引入类型声明以用作函数的返回类型提示,这些函数从不具有return
既不是隐式也不是显式的语句。并且必须通过抛出异常或使用exit/die
函数退出来终止。
function redirect(string $uri): never
{
header('Location: ' . $uri);
exit();
}
这里redirect
称为永不返回函数,因为:
1) 它没有return
明确定义的语句。
function redirect(string $uri): never
{
exit();
return 'something';
}
将产生:
PHP致命错误:一个永不返回的函数不能返回
2) 它没有return
隐式定义的语句。
function redirect(string $uri): never
{
if (false) {
header('Location: ' . $uri);
exit();
}
}
由于这里的条件永远不会满足,因此执行会跳过返回隐式的 if 语句,NULL
这将导致:
PHP致命错误:未捕获的TypeError:redirect():永不返回的函数不能隐式返回
exit
3)它以一个函数结束它的执行
无效vs从不
void
可以有return;
但never
不能。never
强制函数抛出或以 exit/die 终止,但void
不会。never
是 PHP 类型系统中所有其他类型的子类型,包括 void(这允许返回类型协变)。- 两者都不允许返回值。
- 两者都不能用作参数或属性类型。
- 两者都不能用作箭头函数的返回类型。
- 两者都只能用作独立类型(不允许联合或交集)。
何时选择void
,never
反之亦然?
void
当您希望 PHP 在函数调用之后执行下一条语句时,您应该声明一个函数返回类型。never
当您不希望 PHP 在该函数调用之后执行下一条语句时,您应该声明它。
使用never
(PHP 8.1) 您可以保护一个函数,使其永远不会返回,例如,如果您想确保创建的无限循环确实是无限的(从调用站点的角度来看):
<?php
function eternity(string $forEternity): never
{
start:
usleep(1000);
goto start;
}
eternity('the future');
// <- we are here only after the next big-bang, not in this current universe.
这段代码非常简化,通常在这里忘记 goto 语句会触发错误。
无休止的循环通常也不需要保护(因为通常我们永远不希望它们发生),但对于never
函数 to或Exception 总是有用的。die()
exit()
throw
同样,尽管在标准控制流中不推荐使用这三种离开函数的方式(前两种甚至在某些 SAPI 中控制正在运行的进程)。但最后(不是双关语),可以让 IDE 和工具看到函数永远不会直接从代码中编码的返回类型信息返回。这也包括使用此类工具或正在阅读代码的人。
使用void
(PHP 7.1) 您可以确保函数永远不会返回类型,包括底部类型never
(因为您只能使用void
or never
)。
<?php
function back_from_eternity(string $forEternity): void
{
usleep(100000); // not so long
return $forEternity
}
$echo = back_from_eternity('soon');
允许 PHP 防止回声从永恒中恢复,并且让读者发现$echo =
(以及之后对该变量所做的任何事情)仍然需要通常的维护/调试/测试或开发。
- 比较:无效作为返回类型
两者都具有在被违反时抛出的好处,因此程序永远不会按原样继续并呈现函数调用返回 void(所有双关语)。
仍应考虑调用该函数的任何副作用。通常是关于他们的。