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
原文
被defer的方法的参数,是在defer声明的时候就准备好的。如果方法带receiver,则receiver也是在defer声明的时候就准备好的。
例1:
for i := 0; i < 5; i++ {
defer fmt.Printf("%d ", i)
}
output:
4
3
2
1
0
例2:
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()
}
output:
entering: b
in b
entering: a
in a
leaving: a
leaving: b
当声明defer un(trace("b"))的时候,会先把defer un这个方法的参数准备好,也即会执行trace("b")来给被defer的un方法提供参数,所以我们看到entering: b最先打印。
effective_go对此的解释:
it's not block-based but function-based
有疑问加站长微信联系(非本文作者)