2012-11-22 77 views
16

編譯這裏是找到了一些在Go階乘程序:Go代碼不無可達return語句

func factorial(x uint) uint { 
    if x == 0 { 
     return 1 
    } 

    return x * (factorial(x - 1)) 
} 

輸出此功能在輸入5被稱爲是120。然而,當,如果我添加一個else聲明,我收到一個錯誤。

func factorial(x uint) uint { 
    if x == 0 { 
     return 1 
    } else { 
     return x * (factorial(x - 1)) 
    } 
} 

錯誤:function ends without a return statement

我在最後加了return

func factorial(x uint) uint { 
    if x == 0 { 
     return 1 
    } else { 
     return x * (factorial(x - 1)) 
    } 
    fmt.Println("this never executes") 
    return 1 
} 

,我回來的120

預期的輸出爲什麼第二種情況引起的錯誤?爲什麼在第三種情況下,即使該功能從未達到最後的return 1,它會計算正確的輸出?

+1

轉到使用'if cond {return}; (顯然不在一行上)。當循環之後的任何東西都沒有執行時,你有無窮無盡的循環,常見的習慣用法是添加'panic(「unreachable」)'。 –

+0

使最後一個陳述成爲恐慌(「從未到達」) – thwd

回答

22

這是一個衆所周知的編譯器問題。

甚至有記錄的問題:http://code.google.com/p/go/issues/detail?id=65

在Go語言的作者之一的話:

編譯器或者需要退貨或驚慌地在詞法最後 在一個結果函數。這個規則比要求完整的流程控制分析更容易確定函數是否到達末尾 而沒有返回(這通常非常困難),並且比 規則更簡單,以枚舉諸如此類的簡單情況。而且,純粹是詞彙,錯誤不會由於值 中的變化而自發產生,例如函數內控制結構中使用的常量。

-Rob

從另一個評論in golang-nuts,我們可以推斷出它不會被「固定」很快:

這是不是一個錯誤,這是一個經過深思熟慮的設計決定。

-Rob

注意,其他語言如Java有規定,允許該else


2013年3月編輯 -它只是got changed in Go1.1

圍棋1.1之前,該返回值的函數進行明確 「返回」或致電函數結束恐慌;這是一個簡單的方法來讓程序員明確地瞭解 函數的含義。但有很多情況下,最後的「返回」顯然是不必要的,例如只有無限「for」循環的函數。

在Go 1.1中,關於最終「返回」語句的規則更多地是寬鬆的 。它引入了終止語句的概念,該語句保證是函數執行的最後一個語句。 示例包括「for」循環和「if-else」語句,其中每個循環以「return」結束。如果函數的最終 語句可以在語法上顯示爲終止 語句,則不需要最終的「返回」語句。

請注意,該規則純粹是語法:它不關注代碼中的 值,因此不需要複雜的分析。

正在更新:該更改是向後兼容的,但現有的帶有 多餘的「返回」語句和調用恐慌的代碼可能會被手動簡化爲 。這樣的代碼可以通過go vet來識別。

而我提到的問題現在關閉狀態「固定」