6

PHP 8.1 引入了never返回类型,它是什么?never和和有什么区别void

4

2 回答 2

8

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():永不返回的函数不能隐式返回

exit3)它以一个函数结束它的执行

无效vs从不

  • void可以有return;never不能。
  • never强制函数抛出或以 exit/die 终止,但void不会。
  • never是 PHP 类型系统中所有其他类型的子类型,包括 void(这允许返回类型协变)。
  • 两者都不允许返回值。
  • 两者都不能用作参数或属性类型。
  • 两者都不能用作箭头函数的返回类型。
  • 两者都只能用作独立类型(不允许联合或交集)。

何时选择voidnever反之亦然?

void当您希望 PHP 在函数调用之后执行下一条语句时,您应该声明一个函数返回类型。never当您不希望 PHP 在该函数调用之后执行下一条语句时,您应该声明它。

于 2021-07-26T12:13:16.723 回答
0

使用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(所有双关语)。

仍应考虑调用该函数的任何副作用。通常是关于他们的。

于 2021-11-11T15:13:58.417 回答