This question already has an answer here:
I've found a bug in my code
func receive() (err error) {
if v, err := produce(); err == nil {
fmt.Println("value: ", v)
}
return
}
Error is never returning from this function, but I was absolutely sure it should.
After some testing I understood that err
is redeclared in the if statement. More than that - all variables are always redeclared in short variable assignment inside if
statement, despite they were declared before.
This is working code
func receive() (err error) {
v, err := produce()
if err == nil {
fmt.Println("value: ", v)
}
return
}
Here is an example: https://play.golang.org/p/1AWBsPbLiI1
Seems like if statement
//some code
if <init_statement>; <expression> {}
//more code
is equivalent to
//some code
{
<init_statement>
if expression {}
}
//more code
So, my questions:
1) why existing variables are not used
2) why such scoping is not mentioned in documentation/language spec
3) why compiler doesn't say that no one returns a value
</div>
1) Because the language spec says so.
2) It is:
Each "if", "for", and "switch" statement is considered to be in its own implicit block"
3) You did return at the end of your function. Do not use named return values.
A compiler may disallow an empty expression list in a "return" statement if a different entity (constant, type, or variable) with the same name as a result parameter is in scope at the place of the return.
Try to return the value inside if scope and you will get to know that the err variable is shadowed inside the if scope.
func receive1() (err error) {
if v, err := produce(); err != nil {
fmt.Println("value2: ", v)
return // err is shadowed during return
}
return
}
Above code will show an error as:
err is shadowed during return
while in the second function the err declared in the return statement is assigned with local variable scope:
// err is the return value. It's OK
func receive2() (err error) {
v, err := produce()
if err != nil {
fmt.Println("value2: ", v)
return
}
return
}
Try it on playground
The expression list may be empty if the function's result type specifies names for its result parameters. The result parameters act as ordinary local variables and the function may assign values to them as necessary. The "return" statement returns the values of these variables.
func complexF3() (re float64, im float64) {
re = 7.0
im = 4.0
return
}
Regardless of how they are declared, all the result values are initialized to the zero values for their type upon entry to the function. A "return" statement that specifies results sets the result parameters before any deferred functions are executed.