一尘不染

短变量声明和“变量已声明且未使用”错误

go

我偶然发现了一个奇怪的问题,下面的代码无法编译:

func main() {
    var val reflect.Value
    var tm time.Time

    if tm, err := time.Parse(time.RFC3339, "2018-09-11T17:50:54.247Z"); err != nil {
        panic(err)
    }
    val = reflect.ValueOf(tm)

    fmt.Println(val, tm, reflect.TypeOf(tm))
}

错误(代码是linter推荐的代码)。:

$ go run main.go
# command-line-arguments
./main.go:13:5: tm declared and not used

注意,tm确实使用了该变量。

但是,如果我添加了else块-一切都会按预期编译:

func main() {
    var val reflect.Value
    var tm time.Time

    if tm, err := time.Parse(time.RFC3339, "2018-09-11T17:50:54.247Z"); err != nil {
        panic(err)
    } else {
        val = reflect.ValueOf(tm)
    }

    fmt.Println(val, tm, reflect.TypeOf(tm))
}

这看起来像是编译器中的错误,还是一个已知问题?任何想法?(我正在使用go 1.11)

编辑:到目前为止的所有被告。按照:https
:
//golang.org/ref/spec#Short_variable_declarations

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


阅读 302

收藏
2020-07-02

共1个答案

一尘不染

这部分:

if tm, err := time.Parse(...)

创建一个仅在语句中具有作用域的 变量-不是您声明为的变量。tm``if``var tm time.Time

中没有使用此新变量if,因此会出现错误。请注意,您也没有tm分配外部级别,因此fmt.Println将打印零时间,而不是时间.Parse返回。

要解决此问题:声明err并更改if为:

var err error
if tm, err = time.Parse(...)

注意,这在GO中是一件微妙的事情,并且是常见的错误来源。:=实际上,该语句可以与已经声明的变量和一个或多个 变量混合使用(如果已经声明的变量在
同一词法范围内)
。然后,只有新的才被自动声明,:=其余的才被赋值(与一样=)。但是,如果:=在新作用域中使用,则将在该作用域中声明ALL变量,并屏蔽具有相同名称的任何外部作用域变量(例如在if;中;请注意,该if条件不在括号内,但仍视为如果它在{code}块内;forGO中的和其他复合语句也会发生同样的情况。

2020-07-02