defer
1.注意事项和细节
1.1 调用顺序
1.2 defer 拷贝
1.3 defer 与 return 的返回时机
return的返回步骤
函数在返回时,首先函数返回时会自动创建一个返回变量假设为 ret (如果是命名返回值的函数则不会创建),函数返回时要将变量 i 赋值给 ret,即有 ret = i;然后检查函数中是否有 defer 存在,若有则执行 defer 中部分;最后返回 ret;
2.六大原则
defer
后面跟的必须是函数或者方法调用,defer
后面的表达式不能加括号;- 被
defer
的函数或方法的参数的值在定义defer
语句的时候就被确定下来了; - 被
defer
的函数或者方法如果存在多级调用,只有最后一个函数或方法会被defer
到函数 return 或者 panic 之前执行; - 被
defer
的函数执行顺序满足 LIFO 原则,后defer
的先执行; - 被
defer
的函数可以对defer
语句所在的函数的命名返回值做读取和修改操作; - 即使 defer 语句执行了,被 defer 的函数不一定会执行;
3.源码
// A _defer holds an entry on the list of deferred calls.
// If you add a field here, add code to clear it in deferProcStack.
// This struct must match the code in cmd/compile/internal/ssagen/ssa.go:deferstruct
// and cmd/compile/internal/ssagen/ssa.go:(*state).call.
// Some defers will be allocated on the stack and some on the heap.
// All defers are logically part of the stack, so write barriers to
// initialize them are not required. All defers must be manually scanned,
// and for heap defers, marked.
type _defer struct {
started bool //标记是否开始执行defer
heap bool
// openDefer indicates that this _defer is for a frame with open-coded
// defers. We have only one defer record for the entire frame (which may
// currently have 0, 1, or more defers active).
openDefer bool
sp uintptr // sp at time of defer
pc uintptr // pc at time of defer
fn func() // can be nil for open-coded defers
_panic *_panic // panic that is running defer,指向当前执行的panic
link *_defer // next defer on G; can point to either heap or stack!
// If openDefer is true, the fields below record values about the stack
// frame and associated function that has the open-coded defer(s). sp
// above will be the sp for the frame, and pc will be address of the
// deferreturn call in the function.
fd unsafe.Pointer // funcdata for the function associated with the frame
varp uintptr // value of varp for the stack frame
// framepc is the current pc associated with the stack frame. Together,
// with sp above (which is the sp associated with the stack frame),
// framepc/sp can be used as pc/sp pair to continue a stack trace via
// gentraceback().
framepc uintptr
}
最后更新于