这是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%肯定,如果这是输出的确切原因
答案 0 :(得分:2)
在延迟函数中,您可以修改结果参数的值。
调用延迟函数时,return
语句中指定的值已设置。
如果有多个延迟函数,它们将以LIFO顺序执行(后进先出)。
在你的第二个例子中,首先执行fmt.Println()
,然后执行另一个匿名函数。
但是你需要知道,当执行defer
语句时,会立即计算延迟函数的参数,而不是在延迟函数运行时(稍后,在返回之前)。
每次执行“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()
函数。
有关该主题的更多信息,请参阅以下问题/答案: