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

mum43rcc  于 2023-09-28  发布在  Go
关注(0)|答案(2)|浏览(78)

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

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,使用:=,而不是<- line 2示例中的n1
如果你能指出解释这种行为的官方参考,那就更好了。

mklgxw1f

mklgxw1f1#

这是因为你使用了短变量声明:=。引用规范:
与常规变量声明不同,短变量声明可以 * 重新声明 * 变量,前提是它们最初在同一块(或参数列表,如果块是函数体)中以相同类型声明,并且至少有一个非空变量是新的。因此,redeclaration只能出现在多变量短声明中。重新声明不会引入新变量;它只会给原来的值赋一个新值
这一行:

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

这是一个多变量短声明,但是左边的所有变量都已经在同一个块中声明过,所以这也是一个编译时错误(它没有在左边引入任何新变量)。
请注意,如果左侧的所有变量都已经声明过,只需将Short变量声明:=更改为Assignment =即可使其工作(假设右侧的值可以分配给左侧的变量)。

eoigrqb6

eoigrqb62#

检查本官方文件https://go.dev/doc/effective_go中的“重新声明和重新分配”一节。

相关问题