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

标签 go variable-assignment

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

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<- line 2 ,它会提示no new variable on left side of := .

那么,它是如何工作的?为什么编译器愉快地允许覆盖 err在多返回语句中,使用 := ,但不是 n1<- line 2例子?

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

最佳答案

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

Unlike regular variable declarations, a short variable declaration may redeclare variables provided they were originally declared earlier in the same block (or the parameter lists if the block is the function body) with the same type, and at least one of the non-blank variables is new. As a consequence, redeclaration can only appear in a multi-variable short declaration. Redeclaration does not introduce a new variable; it just assigns a new value to the original.

这一行:

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

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

这一行:

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

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

这一行:

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

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

还有这一行:

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

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

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

关于go - 为什么可以在 Go 的多个 return 语句中重新定义 err,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34266337/

相关文章:

c - 为什么我不能从 Golang 中正确读取 C 常量?

java - Java中的final变量什么时候不能再被修改?

javascript - Javascript 对象中的深度合并

c - 表达式必须是可修改的左值

go - 在结构定义之外使用方法的原因是什么?

go - play.golang.org 如何自动管理导入?

methods - 在 golang 中,如何访问采用指针接收器且也在不同包中的方法?

go - 当类型具有处理函数时如何嵌入类型?

r - 使用命名列表转换变量

c - 以不同的方式表达变量赋值