我偶然发现了一个奇怪的问题,下面的代码无法编译:
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确实使用了该变量。
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
与常规变量声明不同,短变量声明可以重新声明变量,前提是它们最初是在相同类型的同一个块中(如果该块是函数体的话,则在参数列表中)被声明为更早,且类型相同,并且至少有一个非空变量是新的。因此,重新声明只能出现在多变量简短声明中。重新声明不会引入新的变量;它只是为原始值分配一个新值。
这部分:
if tm, err := time.Parse(...)
创建一个仅在语句中具有作用域的 新 变量-不是您声明为的变量。tm``if``var tm time.Time
tm``if``var tm time.Time
中没有使用此新变量if,因此会出现错误。请注意,您也没有tm分配外部级别,因此fmt.Println将打印零时间,而不是时间.Parse返回。
if
fmt.Println
要解决此问题:声明err并更改if为:
err
var err error if tm, err = time.Parse(...)
注意,这在GO中是一件微妙的事情,并且是常见的错误来源。:=实际上,该语句可以与已经声明的变量和一个或多个 新 变量混合使用(如果已经声明的变量在 同一词法范围内) 。然后,只有新的才被自动声明,:=其余的才被赋值(与一样=)。但是,如果:=在新作用域中使用,则将在该作用域中声明ALL变量,并屏蔽具有相同名称的任何外部作用域变量(例如在if;中;请注意,该if条件不在括号内,但仍视为如果它在{code}块内;forGO中的和其他复合语句也会发生同样的情况。
:=
=
{code}
for