为什么Go中可以在多个return语句中重新定义err

2024-04-27

考虑下面的示例来说明这个问题(它只是为了解释这个问题而构建的,但我在书中以及实际项目中都看到了类似的代码):

package main

import (
    "strconv"
    "fmt"
    "log"
)

func main() {
    n1, err := strconv.Atoi("1")
    if err != nil {
        log.Panicf("%v", err)
    }

    n2, err := strconv.Atoi("2")
    if err != nil {
        log.Panicf("%v", err)
    }

    // err := fmt.Errorf("new error") <- line 1

    // n1, err := strconv.Atoi("3") <- line 2

    fmt.Printf("n1 = %d, n2 = %d\n", n1, n2)
}

编译器不会抱怨重新定义err,但如果我取消注释<- line 1 or <- line 2,它会抱怨no new variable on left side of :=.

那么它是怎样工作的?为什么编译器乐意允许重写err在多重返回语句中,使用:=, 但不是n1 on <- line 2例子?

如果您能指出解释此行为的官方参考资料,那就更好了。


这是因为你使用了短变量声明 https://golang.org/ref/spec#Short_variable_declarations :=。引用规范:

与常规变量声明不同,短变量声明可以重新声明变量,前提是它们最初在同一块(或参数列表,如果该块是函数体)中以相同的类型声明,并且至少有一个非blank https://golang.org/ref/spec#Blank_identifier变量是新的。作为结果,重新声明只能出现在多变量短声明中。重新声明不会引入新变量;它只是为原始值分配一个新值。

这行:

n1, err := strconv.Atoi("1")

是一个多变量短声明,左侧的所有变量都是新的,因此所有变量都会被声明(并返回值strconv.Atoi()分配)。

这行:

n2, err := strconv.Atoi("2")

它是一个多变量简短声明,并且n2是新的。所以它声明n2并且只分配一个新值err, 因为err已在同一块中声明。

这行:

err := fmt.Errorf("new error") <- line 1

It is not多变量简短声明。它会尝试声明err但它已经在同一个块中声明,因此这是一个编译时错误。

还有这一行:

n1, err := strconv.Atoi("3") <- line 2

这是一个多变量的简短声明,但是所有变量左侧已先前宣布的在同一个块中,所以它也是一个编译时错误(它不会在左侧引入任何新变量)。

请注意,如果左侧的所有变量都已声明过,则只需从 Short 变量声明更改即可:= to 任务 https://golang.org/ref/spec#Assignments =将使其工作(假设右侧的值为可分配的 https://golang.org/ref/spec#Assignability到左侧的变量)。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为什么Go中可以在多个return语句中重新定义err 的相关文章

随机推荐

  • “sed” 在文件中插入反斜杠

    Tool Windows 版 Git Bash Problem 尝试在目录中每个文件的顶部插入文本 connectcentral Code for f in DIR sql do sed i 1i connect central f don
  • iPhone:跳转到uitableview中的下一个uitextfield,如何?

    在我的 iPhone 项目中 我使用 UITableview 和包含 UITextfields 的 UITableViewCells 我在许多应用程序中看到 可以使用下一个按钮跳转到下一个单元格中的下一个文本字段 实现这一目标的最佳方法是什
  • 诊断 Mac OS X 上的堆碎片?

    我正在编写的核心基础应用程序似乎消耗的内存比我实际分配的内存多 根据活动监视器中的 真实内存 计数 我已通过 Instruments 中的 实时字节分配 视图确认我的实际分配符合我的预期 大约 10MB 但活动监视器中的 真实内存 计数显示
  • 轻松安全AppiumService

    我是 Appium 新手 我想使用 Appium 和 C 执行一些 ADB 命令 执行 adb shell ps 的示例 Dictionary
  • 如何延迟forkJoin

    你会怎样拖延 forkJoin 在 rxjs 中 这是我已经拥有但想使用的delay https www learnrxjs io operators utility delay html运营商用那个 return forkJoin thi
  • iOS 内存警告发送到已释放的 UIViewController

    我有奇怪的行为 我的应用程序正在启动UINavigationController 如果我推视图控制器ANavigationController 返回并模拟内存警告一切正常 如果我推相同的视图控制器 ANavigationController
  • 浮点数的最佳中点公式是什么?

    第一个公式 m a b 2 简单 但是存在很大的溢出风险 除了 数值分析 第 9 版伯登和费尔斯指出 当 b a 接近机器的最大精度时 a b 2 有可能返回一个在区间 a b 中不均匀的中点 尽管没有提供进一步的解释 第二个 m a b
  • 如何通过 Angular 6 中的服务将对象发送到不相关的组件?

    所以我是 Angular 的新手 我正在尝试使用服务将对象从组件 1 发送到组件 2 当我将结果记录到 component2 中的控制台时 它没有给我对象的更新值 这可能是因为服务在第二个组件中重新初始化 你能帮忙解决这个问题吗 这是我的代
  • 为什么“(def 元音?(set“aeiou”))”有效?

    我正在看优秀的 Clojure 教程here http ociweb com jnb jnbMar2009 html 在其中一个示例中 它具有如下所示的 Clojure 代码 def vowel set aeiou 这使得元音对于元音返回
  • 如何在vim中的相同行数前面插入多行?

    假设我有两个文本块 其中之一在我的剪贴板中 one two three 另一个位于我正在 vim 中编辑的文件中 AAA BBB CCC 如何在第二个块前面插入第一个块以获得以下结果 oneAAA twoBBB threeCCC 我希望有一
  • html5 下载属性在 FF 中不起作用

    您好 我有一个带有下载属性的锚标记 单击该标记时将从 href 中定义的 url 下载图像 这在 Chrome 中工作正常 但在 Firefox 中它需要浏览器中的图像 有什么办法可以让我们在 FF 中实现这一点吗 a href https
  • BlazorNotifyAuthenticationStateChanged 不会更新基于授权的元素

    我正在实施一个自定义AuthenticationStateProvider并在 mainLayout 中使用来自用户声明的信息 据我了解执行后NotifyAuthenticationStateChanged方法本身应该重新渲染所有使用的组件
  • 带有图像或路径的自定义滑块

    我的 WP7 应用程序中有一个滑块 我想重新设计它的样式 我的默认模板有问题 我做了类似的事情 但我无法将拇指 绑定 到该值
  • R 中独立环境的源脚本,而不是全局环境

    有没有办法source 一个脚本在R这样它就作为父环境附加到全局环境 GlobalEnv 目前 当我获取脚本时 该脚本的所有变量和函数都会出现在我的全局 交互式 环境中 我想将这些变量和函数包含在搜索路径中 但不包含在 GlobalEnv
  • Mockito-thenReturn(true) 仍然在模拟对象上返回 false

    我最近开始阅读有关 Mockito 的内容 根据我的理解 以下代码行必须返回 true 但它返回 false 测试班 public class PersonServiceImplTest Car car InjectMocks CarSer
  • 如何检测 JavaScript 中的哈希值后 URL 是否已更改

    如何在 JavaScript 中检查 URL 是否已更改 例如 像 GitHub 这样使用 AJAX 的网站将在 符号后附加页面信息 以创建唯一的 URL 而无需重新加载页面 检测此 URL 是否发生变化的最佳方法是什么 Is the on
  • 何时何地获取腕表复杂功能的数据

    经过几天的复杂工作后 我有信心对按规定间隔发生的更新的更新过程进行以下说明 The system calls requestedUpdateDidBegin This is where you can determine if your d
  • 用户 postgres 启动进程使所有 CPU 达到 100% 使用率

    用户 postgres 正在运行一个进程 该进程在 centos 机器上以 100 使用率占用所有 CPU postgresql 服务未运行 因此它不能是查询 当我尝试停止该进程时 它会自行重新启动 然后进程的名字就有点奇怪了 恭喜 通过将
  • 在 swift 中将参数传递给 #selector 方法[重复]

    这个问题在这里已经有答案了 我想在单击图像时将多个参数传递给函数 这是我的代码 var param1 120 var param2 hello var param3 world let image UIImage UIImage named
  • 为什么Go中可以在多个return语句中重新定义err

    考虑下面的示例来说明这个问题 它只是为了解释这个问题而构建的 但我在书中以及实际项目中都看到了类似的代码 package main import strconv fmt log func main n1 err strconv Atoi 1