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

时间:2015-12-14 11:50:22

标签: 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 :=

那么,它是如何运作的?为什么编译器允许在{return返回语句中使用err,而不是:=上的n1覆盖<- line 2

如果你能指出解释这种行为的官方参考,那就更好了。

1 个答案:

答案 0 :(得分:12)

这是因为您使用了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左侧的变量。)