我尝试学习golang并使用有效的go作为讲座。我坚持资本延期,看下面的代码
package main
import "fmt"
func trace(s string) string {
fmt.Println("entering:", s)
return s
}
func un(s string) {
fmt.Println("leaving:", s)
}
func a() {
defer un(trace("a"))
fmt.Println("in a")
}
func b() {
defer un(trace("b"))
fmt.Println("in b")
a()
}
func main() {
b()
}
作为输出我已经
entering: b
in b
entering: a
in a
leaving: a
leaving: b
我知道,defer语句将在函数中的return语句之后执行。但在这里,为什么输入:b是第一个输出?我预计在b中作为第一个输出!
答案 0 :(得分:8)
根据http://golang.org/doc/effective_go.html#defer:
延迟函数的参数(如果函数是方法,包括接收器)在延迟执行时计算,而不是在调用执行时计算。除了避免担心变量在函数执行时更改值,这意味着单个延迟调用站点可以推迟多个函数执行。
所以推迟函数的参数(在你的情况下跟踪(" b"))首先评估
答案 1 :(得分:2)
简化,
package main
import "fmt"
func trace(s string) string {
fmt.Println("entering:", s)
return s
}
func un(s string) {
fmt.Println("leaving:", s)
}
func b() {
defer un(trace("b"))
fmt.Println("in b")
}
func main() {
b()
}
输出:
entering: b
in b
leaving: b
因为"在defer
执行"时评估延迟函数的参数,
defer un(trace("b"))
函数b
中的语句是使用显式范围,等同于
{
unarg := trace("b")
defer un(unarg)
}
因此,等效地,
package main
import "fmt"
func trace(s string) string {
fmt.Println("entering:", s)
return s
}
func un(s string) {
fmt.Println("leaving:", s)
}
func b() {
{
unarg := trace("b")
defer un(unarg)
}
fmt.Println("in b")
}
func main() {
b()
}
输出:
entering: b
in b
leaving: b
等效地,完整的例子,
package main
import "fmt"
func trace(s string) string {
fmt.Println("entering:", s)
return s
}
func un(s string) {
fmt.Println("leaving:", s)
}
func a() {
{
unarg := trace("a")
defer un(unarg)
}
fmt.Println("in a")
}
func b() {
{
unarg := trace("b")
defer un(unarg)
}
fmt.Println("in b")
a()
}
func main() {
b()
}
输出:
entering: b
in b
entering: a
in a
leaving: a
leaving: b