函数返回的常量是否自动成为命名返回变量

时间:2015-10-19 10:51:30

标签: function go return-value

这是Golang中的一个函数,它使用defer来改变函数c()的命名返回值。

package main

import "fmt"

func c() (i int) { 
    defer func() {  }()     
    defer fmt.Println("our i is", i)
    return 45
   }

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

该计划的输出是:

  

我们的我是0

     

45

更改代码中的匿名func()

func c() (i int) { 
        defer func() { i = 1 }()   
        defer fmt.Println("our i is", i)
        return 45
       }

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

这导致输出:

  

我们的我是0

     

1

如果没有其他值放入i中,似乎返回值45会自动复制到i。但我不是100%肯定,如果这是输出的确切原因

1 个答案:

答案 0 :(得分:2)

在延迟函数中,您可以修改结果参数的值。

调用延迟函数时,return语句中指定的值已设置。

如果有多个延迟函数,它们将以LIFO顺序执行(后进先出)。

在你的第二个例子中,首先执行fmt.Println(),然后执行另一个匿名函数。

但是你需要知道,当执行defer语句时,会立即计算延迟函数的参数,而不是在延迟函数运行时(稍后,在返回之前)。

Spec: Defer statements:

  

每次执行“defer”语句时,调用的函数值和参数都是evaluated as usual并重新保存,但不调用实际函数。而是在周围函数返回之前立即调用延迟函数,其顺序与延迟相反。

所以这一行:

defer fmt.Println("our i is", i)

永远是指用fmt.Println()参数调用i = 0

fmt.Println("our i is", 0)

因为当此行投放时,i的值为0

所以在你的第二个例子中fmt.Println()打印0,然后运行另一个将i设置为1的延迟函数,这就是返回的内容。

您的第一个示例只打印了一些内容(i = 0),但第一个示例中的延迟函数不会修改i的值,因此将返回45(并由来自fmt.Println())的main()函数。

有关该主题的更多信息,请参阅以下问题/答案:

Defer usage clarification

How to return a value in a Go function that panics?