Effictive Go

61 阅读1分钟
  • Defer
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

然而我一开始以为是

in b
in a
entering:a
leaving:a
entering:b
leaving:b

这是因为没考虑到defer的执行机制:defer以defer初次定义时的注入参数值,作为defer函数被调用时的注入参数(function)。因此在defer un(trace("a"))和defer un(trace("b"))中,注入参数即trace("a")和trace("b")被立即执行。

原文:The arguments to the deferred function (which include the receiver if the function is a method) are evaluated when the defer executes, not when the call executes. Besides avoiding worries about variables changing values as the function executes, this means that a single deferred call site can defer multiple function executions. Here's a silly example.