【问题标题】:Go code doesn't compile without an unreachable return statement如果没有无法访问的 return 语句,Go 代码将无法编译
【发布时间】:2016-03-31 19:25:37
【问题描述】:

这是在 Go 中求一个数的阶乘的程序:

func factorial(x uint) uint {
    if x == 0 {
        return 1
    }

    return x * (factorial(x - 1))
}

在输入 5 上调用此函数时的输出为 120。但是,如果我添加 else 语句,则会出现错误。

func factorial(x uint) uint {
    if x == 0 {
        return 1
    } else {
        return x * (factorial(x - 1))
    }
}

错误:function ends without a return statement

我在末尾添加了return

func factorial(x uint) uint {
    if x == 0 {
        return 1
    } else {
        return x * (factorial(x - 1))
    }
    fmt.Println("this never executes")
    return 1
}

我得到了 120 的预期输出。

为什么第二种情况会导致错误?为什么在第三种情况下,即使函数从未到达最后一个return 1,它也会计算出正确的输出?

【问题讨论】:

  • 在 Go 中使用 if cond {return}; return 是惯用的(显然不是一行)。当你有无限的 for 循环并且循环之后的任何内容都不会执行时,常见的习惯用法是添加 panic("unreachable")
  • 将最后一条语句设为panic("never reached")
  • 标记为离题并投票关闭,因为此“编译器错误”已修复,相关代码不再导致编译器错误。

标签: go


【解决方案1】:

这是一个众所周知的编译器问题。

甚至记录了一个问题:http://code.google.com/p/go/issues/detail?id=65

用 Go 语言的一位作者的话来说:

编译器要求返回或恐慌在词法上最后 在一个有结果的函数中。这条规则比要求完整 流控分析判断一个函数是否到达终点 不返回(这通常很难),并且比 列举简单案例的规则,例如这个。还有,纯粹 词法上,错误不会由于值的变化而自发产生 比如函数内部控制结构中使用的常量。

-抢劫

从另一条评论in golang-nuts,我们可以推断它不会很快“修复”:

这不是错误,而是经过深思熟虑的设计决定。

-抢劫

请注意,Java 等其他语言的规则允许 else


2013 年 3 月编辑 - 只是 got changed in Go1.1

在 Go 1.1 之前,返回值的函数需要显式 “返回”或在函数结束时调用恐慌;这是一个 让程序员明确理解含义的简单方法 功能。但在很多情况下,最终的“回报”显然是 不必要的,例如只有无限“for”循环的函数。

在 Go 1.1 中,关于最终“return”语句的规则更多 允许的。它引入了终止语句的概念, 保证是函数执行的最后一条语句。 示例包括没有条件的“for”循环和“if-else” 每一半都以“返回”结尾的语句。如果决赛 函数的语句可以在语法上显示为终止 声明,不需要最后的“return”声明。

请注意,该规则是纯粹的句法:它不注意 代码中的值,因此不需要复杂的分析。

更新:更改是向后兼容的,但现有代码与 可以简化多余的“返回”语句和对恐慌的调用 手动。此类代码可以通过 go vet 识别。

我提到的问题现在以状态“已修复”关闭。

【讨论】:

    猜你喜欢
    • 2021-02-28
    • 1970-01-01
    • 2016-05-23
    • 1970-01-01
    • 2023-04-06
    • 2011-10-31
    • 1970-01-01
    • 2020-07-14
    • 1970-01-01
    相关资源
    最近更新 更多