2017-07-21 162 views
3

我正在讀取一些在github上用golang編寫的代碼,並且發現了非常有趣的一段代碼。我將其簡化爲明確。在函數中返回值爲空的返回值golang

func Insert(docs ...interface{}) (err error) { 
    for i := 0; i < 3; i++ { 
     err = fmt.Errorf("") 
     if err.Error()!="EOF" { 
      return 
     } 
    } 
    return err 
} 

我對這裏的空迴歸非常困惑......它是如何工作的?他返回零作爲錯誤或循環休息?我明白,這個問題看起來是虛構的,但我無法在go docs上找到任何有關這方面的信息......另外,我不明白我們如何返回err,也就是說,據我所知,以某種方式宣佈返回。 (err錯誤)是否意味着我們的func中已經有了一個錯誤變量,如果沒有指定,它將用作默認返回值?那麼爲什麼我們在func的結尾隱含地返回err?

我會非常樂意解釋。

+1

見 「命名的返回值」 中的[ 「圍棋之旅」(https://tour.golang.org/basics/7)和[ 「有效圍棋」(HTTPS ://golang.org/doc/effective_go.html#named-results) – JimB

回答

6

該函數使用「命名」返回值。在return語句

the spec:如果函數的結果類型 指定其結果參數名稱

表達列表可能爲空。結果參數作爲普通局部變量執行 ,並且該功能可以根據需要爲其分配值 。 「return」語句返回這些變量的值。

不管它們是如何宣佈,所有的結果值有 初始化至零個值入境後到 函數的類型。指定結果的「return」語句會在執行任何延遲函數之前設置結果 參數。

使用命名的回報,您可以節省手動分配的局部變量一些代碼,有時可能會清理雜亂的if/else語句或返回值的長列表。

func a()(x []string, err error){ 
    return 
} 

實際上只是

func a() ([]string,error){ 
    var x []string 
    var err error 
    return x,err 
} 

它有點短速記,我同意,它可能不那麼明顯。

命名的返回有時是需要的,因爲它允許像在延遲函數內部訪問它們那樣的東西,但根據我可以判斷,裸返回只是語法糖,並且從不被嚴格要求。

我經常看到的一個地方是在函數中有很多返回值的錯誤返回情況。

if(err != nil){ 
    return 
} 
return a,b,c,nil 

是很容易,

if(err != nil){ 
    return nil,nil,nil,err 
} 
return a,b,c,nil 

當你把它寫了一堆倍。如果您將簽名更改爲具有其他「真實」返回值,則不必修改這些返回值。

我在我剛剛搜索的代碼庫中使用它們的大多數地方,它們肯定似乎隱藏了其他的氣味,比如過於複雜的多用途功能,太深的if/else嵌套以及類似的東西。

+0

你可以發表一些例子,其中這種類型的聲明清理如果是或類似的東西?對我來說,這種語言功能看起來像一個糟糕的設計(我來自C#) –

+2

我沒有強烈的使用裸返回的參數,並且通常默認爲顯式。但我編輯了一些更多的考慮。 – captncraig

+0

非常感謝您的回覆,現在我完全理解了這個問題! :) –

3

當你有一個命名返回值(err這裏):

func Insert(docs ...interface{}) (err error) { 

這由名字創建了一個函數局部變量,如果你只需要調用return不帶參數,它返回本地變量。因此,在這個功能,

return 

是一樣的,並暗示,

return err 

這是詳細in the tourin the spec

+0

好的,但是爲什麼我們使用空迴歸並隱式地在func結尾寫回return err? –

+2

絕對沒有理由。保持一致可能會更好。 – Adrian

+1

@AlexVoskresenskiy在[這個問題]的一些很好的答案(https://stackoverflow.com/questions/15089726/why-should-return-parameters-be-named) – captncraig

2

Go的返回值可能會被命名。如果是這樣,它們被視爲在函數頂部定義的變量。

package main 

import "fmt" 

func split(sum int) (x, y int) { 
    x = sum * 4/9 
    y = sum - x 
    return 
} 

func main() { 
    fmt.Println(split(17)) 
} 

https://tour.golang.org/basics/7