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

huangapple go评论88阅读模式
英文:

Does a constant returned by a function automatically become the value of the named return variable

问题

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

package main

import "fmt"

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

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

程序的输出结果是:

our i is 0

45

在代码中更改匿名函数的部分:

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

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

这将导致输出结果为:

our i is 0

1

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

英文:

This is a function in Golang that uses defer to alter the named return value of the function 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()) 
 }

The output of the program is:

> our i is 0
>
> 45

changing the anonymous func() in the code

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

This results in the output:

> our i is 0
>
> 1

It seems like the return value 45 is copied to i automatically if no other value is being put inside i. But I am not a 100% sure if that is the exact reason for the output

答案1

得分: 2

在延迟函数中,你有机会修改结果参数的值。

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

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

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

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

规范:延迟语句(Defer statements):

> 每次执行 "defer" 语句时,函数值和调用的参数会像通常一样进行求值并重新保存,但实际的函数不会被调用。相反,延迟函数会在包围它们的函数返回之前立即被调用,按照它们被延迟的相反顺序。

所以这行代码:

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

将始终意味着使用 i = 0 参数调用 fmt.Println()

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

因为当这行代码运行时,i 的值为 0

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

你的第一个例子只是打印出一些内容(i = 0),但是第一个例子中的延迟函数不会修改 i 的值,所以将返回 45(并由 main() 中的 fmt.Println() 函数打印出来)。

请参考以下问题/答案以了解更多相关内容:

https://stackoverflow.com/questions/31404471/defer-usage-clarification

https://stackoverflow.com/questions/33167282/how-to-return-a-value-in-a-go-function-that-panics

英文:

In deferred functions you have the opportunity to modify the values of the result parameters.

When deferred functions are called, values specified in the return statement are already set.

If there are multiple deferred functions, they are executed in LIFO order (last in, first out).

In your second example fmt.Println() is executed first, then the other, anonymous function.

But what you need to know that when the defer statement is executed, the arguments to the deferred function are evaluated immediately, not when the deferred function will be run (later, before returning).

Spec: Defer statements:

> Each time a "defer" statement executes, the function value and parameters to the call are evaluated as usual and saved anew but the actual function is not invoked. Instead, deferred functions are invoked immediately before the surrounding function returns, in the reverse order they were deferred.

So this line:

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

Will always mean to call fmt.Println() with i = 0 argument:

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

Because when this line runs, i has a value of 0.

So in your 2nd example fmt.Println() prints 0, then runs the other deferred function which sets i to 1 and this is what is returned.

Your first example just prints something (i = 0), but the deferred functions in the first example do not modify the value of i so 45 will be returned (and printed by the fmt.Println() function from the main()).

Please see the following questions/answer for more on the topic:

https://stackoverflow.com/questions/31404471/defer-usage-clarification

https://stackoverflow.com/questions/33167282/how-to-return-a-value-in-a-go-function-that-panics

huangapple
  • 本文由 发表于 2015年10月19日 18:51:29
  • 转载请务必保留本文链接:https://go.coder-hub.com/33212539.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定