PHP 8.1 推出了 never
返回类型,它是什么?和 void
有什么区别?
PHP 8.1 推出了 never
返回类型,它是什么?和 void
有什么区别?
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致命错误:Uncaught TypeError:redirect():不能隐式返回从不返回的函数
3) 函数以exit
函数结束其执行
void
可以使用return;
,但never
不能。never
强制函数抛出异常或使用exit/die终止,但void
不需要。never
是PHP类型系统中所有其他类型的子类型,包括void(这允许返回类型协变)。void
或never
?当您期望PHP在函数调用后执行下一条语句时,请声明函数返回类型为void
。当您不希望PHP在函数调用后执行下一条语句时,请声明函数返回类型为never
。
使用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语句会触发错误。
无限循环通常也不必要用于保护for(因为通常我们永远不希望它们发生),但never
对于函数执行die()
、exit()
或throw
异常是有用的,总是需要的。
虽然这三种离开函数的方式在标准控制流中并不被推荐使用(前两种甚至在某些SAPI中控制着运行进程)。但最后(无意冒犯),通过在代码中编码的返回类型信息,IDE和工具可以看到一个函数从不会返回。这也包括使用这些工具或阅读代码的人类。
使用void
(PHP 7.1)可以保证函数永远不会返回类型,包括底部类型never
(因为你只能使用void
或者 never
)。
<?php
function back_from_eternity(string $forEternity): void
{
usleep(100000); // not so long
return $forEternity
}
$echo = back_from_eternity('soon');
这个功能可以让PHP防止永远回传echo,也可以让读者知道$echo =
(以及后续对该变量的任何操作)仍然需要常规的维护/调试/测试或开发。
两者都有一个好处,即在违反规则时会抛出异常,因此程序永远不会像原样继续运行并返回void(所有双关语都是有意的)。
调用函数产生的任何副作用仍应被考虑。通常就是这个问题。
never
的一个可能用例是始终抛出异常。虽然有用,但我之前没有在其他地方看到过它被提到。 - MAChitgarha