2013-02-26 45 views
22

命名函數的返回參數有什麼好處?爲什麼要命名返回參數?

func namedReturn(i int) (ret int) { 
    ret = i 
    i += 2 
    return 
} 

func anonReturn(i int) int { 
    ret := i 
    i += 2 
    return ret 
} 
+0

要添加到@thomaskappler的答案和那裏的討論(我還沒有評論),您可以使用命名結果參數,並在返回中指定變量。這提供了文檔的好處,但消除了影子問題。但是,它確實消除了>如果您有多個返回站點,則如果您更改函數的返回值,則不需要全部更改它們,因爲它只會說「返回」。效益。 – darkwing 2017-05-25 20:10:18

回答

28

有命名他們一些好處:

  • 它作爲文檔。
  • 它們被自動聲明並初始化爲零值。
  • 如果你有多個返回地址,如果你改變了函數的返回值,你不需要全部改變它們,因爲它只會說「return」。

也有缺點,主要是很容易通過聲明一個相同名稱的變量來隱藏它們。

Effective Go有section on named result parameters

+4

陰影是一個主要問題。我經常有這樣的事情:'我,錯誤:= strconv.Atoi(...)'。 '我'是一個局部變量,但我想err是一個返回值。爲了得到這個工作,我必須先聲明我,而不是使用:= – tjameson 2013-03-09 12:07:21

+0

「它們被自動聲明並初始化爲零值。」 - 我不明白這是一種好處。一般來說,Golang非常自然地冒險從metod返回一個值,並期望客戶端代碼知道這是在沒有其他值返回的情況下自動返回的默認值。 – luqo33 2017-03-25 15:56:59

3

這是非常有用的,至少兩種情況:

  1. 每當你必須聲明你要回歸變量。例如。

    func someFunc() (int, error) { 
        var r int 
        var e error 
        ok := someOtherFunc(&r) // contrived, I admit 
        if !ok { 
         return r, someError() 
        } 
        return r, nil 
    } 
    

    func someFunc() (r int, e error) { 
        ok := someOtherFunc(&r) 
        if !ok { 
         e = someError() 
        } 
        return 
    } 
    

    這得到作爲通過函數增加的執行路徑的數目更重要。

  2. 當您記錄返回值並希望按名稱引用它們時。 godoc考慮函數簽名的返回變量部分。

2

例如,名稱返回參數可以通過名稱訪問。

func foo() (a, b, c T) { 
     // ... 
     if qux { 
       b = bar() 
     } 
     // ... 
     return 
} 

這不容易複製不帶名稱的返回參數。人們必須引入與已命名的返回參數基本相同的局部變量:

func foo() (T, T, T) { 
     var a, b, c T 
     // ... 
     if qux { 
       b = bar() 
     } 
     // ... 
     return a, b, c 
} 

因此,更容易直接進行。

此外,他們也通俗易懂的另一個方向:

func foo() (a, b, c T) { 
     // ... 
     if a > c { 
       b = bar() 
     } 
     // ... 
     return 
} 

等等

16

名爲返回變量的另一種特殊的用途是通過遞延函數文本被捕獲。一個簡單的例子:

package main 

import (
    "errors" 
    "fmt" 
) 

func main() { 
    fmt.Println(f()) 
} 

var harmlessError = errors.New("you should worry!") 

func f() (err error) { 
    defer func() { 
     if err == harmlessError { 
      err = nil 
     } 
    }() 
    return harmlessError 
} 

輸出是<nil>。在更實際的情況下,延遲函數可能處理恐慌,並且可能會修改除錯誤結果之外的其他返回值。然而,通常的奇妙之處在於,延遲字面量有機會在f被終止後正常或恐慌地修改f 的返回值。

+0

即使err在f()內本地聲明,然後被延遲使用,f()也不會以同樣的方式工作嗎? => func f()(err error){} @sonia – 2015-10-20 11:19:13

相關問題