2013-02-26 119 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

相关问题