考虑以下示例来说明问题(它只是为了解释问题而构建的,但我在书中看到了类似的代码以及实际项目中的代码):
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变量声明 :=
.引用规范:
与常规变量声明不同,短变量声明可以重新声明变量,前提是它们最初在同一个块中声明(或者如果块是函数体,则参数列表)具有相同的类型,并且至少有一个非空变量是新的.因此,重新声明只能出现在多变量简短声明中.重新声明不会引入新变量; 它只是为原始分配一个新值.
这一行:
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即可 =
使其工作(右侧的假定值可分配给左侧的变量).