【问题标题】:Why it is possible to redefine err in multiple return statement in Go为什么可以在 Go 的多个 return 语句中重新定义 err
【发布时间】:2016-03-19 21:25: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,但如果我取消注释&lt;- line 1&lt;- line 2,它会抱怨no new variable on left side of :=

那么,它是如何工作的?为什么编译器允许在多返回语句中覆盖 err,使用 :=,而不是 &lt;- line 2 示例中的 n1

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

【问题讨论】:

  • 嗯,我差不多写完了gopl.io(虽然重点是数据类型、方法、接口、并发),并且阅读了有效的go,以及其他资源(虽然通常是我当下感兴趣的话题) ,我用 Go 进行算法比赛,以及构建 CLI 工具。我的意思是阅读文档是一件好事,但构建事物和构建学习语言的同时要好得多,对我来说,这是一种平衡,在学习时间与构建(获得结果)事物之间的时间。尤其是当您开始学习一门新语言时,您希望看到结果以继续学习。
  • 当我谈到 CLI 时,我的意思是使用 crypto/ssh/net/http/base64/yaml 和其他包,以及 go-bindata :),就像总体概述一样 :)跨度>
  • 但是,感谢您在有效的 go doc 中提及这一点。

标签: go variable-assignment


【解决方案1】:

因为你使用了Short variable declaration:=。引用规范:

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

这一行:

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

是多变量短声明,左边所有变量都是新的,所以都会被声明(并赋值strconv.Atoi()的返回值)。

这一行:

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

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

这一行:

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

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

还有这一行:

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

它是一个多变量短声明,但是左侧的所有变量都已经之前声明过在同一个块中,所以它也是一个编译-时间误差(它不会在左侧引入任何新变量)。

请注意,如果左侧的所有变量之前都已声明,只需将短变量声明 := 更改为 Assignment = 即可使其工作(假设右侧的值为 assignable 为左侧的变量)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-03-15
    • 2022-12-09
    • 2016-05-26
    • 2011-11-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-06-26
    相关资源
    最近更新 更多