I\'ve stumbled across a strange issue where the code below fails to compile:
func main() {
var val reflect.Value
var tm time.Time
if tm, err := time
Your if
statement declares a new variable tm
that exists only within the scope of the if
block and is indeed never used:
if tm, err := time.Parse(time.RFC3339, "2018-09-11T17:50:54.247Z"); err != nil {
panic(err)
}
In Go, :=
declares a new variable and initializes it. You probably meant:
func main() {
var val reflect.Value
var tm time.Time
var err error
// Note the change to normal assignment here instead of :=
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))
}
The :=
shortcut operator is demonstrated in the Tour of Go and explained in the Go spec, the latter of which includes:
It is shorthand for a regular variable declaration with initializer expressions but no types:
"var" IdentifierList = ExpressionList .
Scoping is explained in the Go spec as well.
This part:
if tm, err := time.Parse(...)
creates a new variable tm
that has scope only within the if
statement - it is NOT the one you declared as var tm time.Time
.
This new variable is not used within the if
, therefore you get the error. Note you also don't get the outer-level tm
assigned, so fmt.Println
will print the zero time, not what time.Parse returned.
To fix this:
declare err
and change your if
to read:
var err error
if tm, err = time.Parse(...)
NOTE this is a subtle thing in GO and a fairly common source of mistakes. The :=
statement can in fact be used with a mix of variables that are already declared and one or more new variables - if the already-declared ones are in the same lexical scope. Then, only the new ones are auto-declared by :=
and the rest are just assigned (as with =
). However, if you use :=
in a new scope, then ALL variables are declared in that scope and mask any outer-scope variables with the same name (such as in an if
; note that the if
condition is not inside the braces, but is still considered as if it were within the {code}
block; same happens with the for
and other compound statements in GO).