我刚开始学习Go语言,看到The Go Blog - Defer, Panic, and Recover的一个例子中使用defer来改变有名返回值,让我产生了困惑。
这个例子说:
- 延迟函数可以读取和赋值给返回函数的命名返回值。
在这个例子中,一个被延迟的函数会在包裹函数返回后将返回值 i 加1。因此,这个函数返回 2:
func c() (i int) {
defer func() { i++ }()
return 1
}
但是根据我从Go之旅-命名返回值学到的知识:
没有参数的返回语句返回带有名称的返回值。 这被称为“裸”的返回。
我在以下代码中进行了测试,并且在函数b
中返回1,因为它不是上面提到的“没有参数的返回语句”的情况。
func a() (i int) { // return 2
i = 2
return
}
func b() (i int) { // return 1
i = 2
return 1
}
所以我的问题是,在第一个例子中,包围函数c具有命名返回值i,但函数 c 使用return 1
,在第二个例子中,无论i
的值是什么,它都应该返回1。但是为什么在延迟函数更改 i 的值后, c 函数返回 i 的值而不是1?
当我输入问题时,我可能已经猜到答案了。那是因为:
return 1
等于:
i = 1
return
在一个具有命名返回值变量i的函数中?请帮我确认,谢谢!
func c
的情况下更改返回值。因此,执行顺序应为:i = 1
(赋值)、i++
(延迟执行递增)、return
,返回值为2。 - Elias Van Ootegemdefer
的“后进先出”特性已经很清楚了。如果你的回答更关注返回值,那就太好了。谢谢。Go真是一个不错的语言。 - Long