为什么要命名返回参数?

时间:2013-02-26 12:57:01

标签: go

命名函数的返回参数会带来什么好处?

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

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

4 个答案:

答案 0 :(得分:37)

命名它们有一些好处:

  • 它作为文件。
  • 它们被自动声明并初始化为零值。
  • 如果您有多个返回网站,如果您更改了该功能的返回值,则无需全部更改它们,因为它只会说“返回”。

还有一些缺点,主要是通过声明一个同名变量很容易意外地影响它们。


Effective Go有section on named result parameters

  

Go函数的返回或结果“参数”可以给出名称   并用作常规变量,就像传入的参数一样。什么时候   命名时,它们被初始化为其类型的零值   功能开始;如果函数执行带有的return语句   没有参数,结果参数的当前值用作   返回的值。

     

名称不是强制性的,但可以缩短代码   更清楚:他们是文件。如果我们将nextInt的结果命名为它   变得明显,返回int是哪个。

func nextInt(b []byte, pos int) (value, nextPos int) {
     

[...]

答案 1 :(得分:20)

命名返回变量的另一个特殊用途是由延迟函数文字捕获。一个简单的例子:

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 的返回值,无论是正常还是恐慌。

答案 2 :(得分:3)

至少在两种情况下有用:

  1. 每当您必须声明要返回的变量时。 E.g。

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

    VS

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

    随着通过函数的执行路径数量的增加,这变得更加重要。

  2. 当您记录返回值并希望按名称引用它们时。 godoc认为返回变量是函数签名的一部分。

答案 3 :(得分: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
}