Instead, deferred functions are invoked immediately before the surrounding function returns, in the reverse order they were deferred.(defer函数在它被返回之前进行调用,以defer声明的逆序调用)
If the deferred function is a function literal and the surrounding function has named result parameters that are in scope within the literal, the deferred function may access and modify the result parameters before they are returned
看下面的例子。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
funcTestDeferParam(t *testing.T) { fmt.Printf("with named param, x: %d\n", withNamedParam()) fmt.Printf("without named param, x: %d\n", withoutNamedParam()) } funcwithNamedParam()(x int) { x = 99 deferfunc() { x = 100 }() return x }
funcwithoutNamedParam()int { x := 99 deferfunc() { x = 100 }() return x }
运行结果
1 2
with named param, x: 100 without named param, x: 99
Calling g. Printing in g 0 Printing in g 1 Printing in g 2 Printing in g 3 Panicking! Defer in g 3 Defer in g 2 Defer in g 1 Defer in g 0 Recovered in f 4 Returned normally from f.
funcnewdefer(siz int32) *_defer { var d *_defer gp := getg() // get the current goroutine [...] // deferred list is now attached to the new _defer struct d.link = gp._defer gp._defer = d // the new struct is now the first to be called return d }
defer函数的调用会以出栈的方式进行调用
1 2 3 4 5 6 7 8 9 10 11 12 13
funcdeferreturn(arg0 uintptr) { gp := getg() // get the current goroutine d:= gp._defer // copy the deferred function to a variable if d == nil { // if there is not deferred func, just return return } [...] fn := d.fn // get the function to call d.fn = nil// reset the function gp._defer = d.link // attach the next one to the goroutine freedefer(d) // freeing the _defer struc jmpdefer(fn, uintptr(unsafe.Pointer(&arg0))) // call the func }