Here is the program to find the factorial of a number in Go:
func factorial(x uint) uint {
if x == 0 {
return 1
}
return x * (factorial(x - 1))
}
The output for this function when called on input 5 is 120. However, if I add an else
statement I get an error.
func factorial(x uint) uint {
if x == 0 {
return 1
} else {
return x * (factorial(x - 1))
}
}
Error : function ends without a return statement
I added a return
at the end :
func factorial(x uint) uint {
if x == 0 {
return 1
} else {
return x * (factorial(x - 1))
}
fmt.Println("this never executes")
return 1
}
and I get back the expected output of 120.
Why would the second case cause an error? Why in the third case even though the function never reaches the last return 1
, it computes the correct output?
This is a well known problem of the compiler.
There is even an issue logged : http://code.google.com/p/go/issues/detail?id=65
In the words of one of the authors of the Go language:
The compilers require either a return or a panic to be lexically last in a function with a result. This rule is easier than requiring full flow control analysis to determine whether a function reaches the end without returning (which is very hard in general), and simpler than rules to enumerate easy cases such as this one. Also, being purely lexical, the error cannot arise spontaneously due to changes in values such as constants used in control structures inside the function.
-rob
From another comment in golang-nuts, we can infer it's not going to be "fixed" soon :
It's not a bug, it's a deliberate design decision.
-rob
Note that other languages like Java have rules allowing this else
.
March 2013 EDIT - It just got changed in Go1.1 :
Before Go 1.1, a function that returned a value needed an explicit "return" or call to panic at the end of the function; this was a simple way to make the programmer be explicit about the meaning of the function. But there are many cases where a final "return" is clearly unnecessary, such as a function with only an infinite "for" loop.
In Go 1.1, the rule about final "return" statements is more permissive. It introduces the concept of a terminating statement, a statement that is guaranteed to be the last one a function executes. Examples include "for" loops with no condition and "if-else" statements in which each half ends in a "return". If the final statement of a function can be shown syntactically to be a terminating statement, no final "return" statement is needed.
Note that the rule is purely syntactic: it pays no attention to the values in the code and therefore requires no complex analysis.
Updating: The change is backward-compatible, but existing code with superfluous "return" statements and calls to panic may be simplified manually. Such code can be identified by go vet.
And the issue I mentioned is now closed with status "Fixed".