文章目录
defer会把声明的 延迟函数以及 函数的入参放到栈上,当外部的包含方法return之前,返回参数到调用方法之前调用。在defer语句声明的时候入参就已经确定下来了,所以如果要传入指定参数那么就要在defer前给入参赋值。
延迟函数的参数在defer语句出现时就已经确定下来了
type struct student{
name string
}
func (st *student)fn(){
defer fmt.Println(st.name)
st.name = "zhangsan"
return
}
defer 会打印 空字符串,name 的值在defer语句声明的时候就已经确定下来了,即拷贝了一份存到了栈上,后面的修改不会影响已经拷贝的数据。
延迟函数没有入参时,延迟函数体内的变量会受到影响
type struct student{
name string
}
func (st *student)fn(){
defer func(){
fmt.Println(st.name)
}()
st.name = "zhangsan"
return
}
defer 打印 zhangsan,name并没有当做参数传进去,defer只是保存了一份匿名函数在栈上,执行匿名函数的时候才会去找name的值。
延迟函数 可以 修改主函数的 具名 返回值
func fn() (result int) {
i := 1
defer func() {
result++
}()
return i
}
fn()返回 2。关键字return不是一个原子操作,实际上return只代理汇编指令ret,即将跳转程序执行;return实际上分两步:首先将 i 存入栈中作为返回值,然后跳转程序执行,而defer的执行时机正是跳转前,所以说defer执行时还是有机会操作返回值的。
即: result = i --> result++ --> return
延迟函数 无法 修改主函数的 匿名 返回值
func fn() int {
var i int
defer func() {
i++
}()
return i
}
上面的函数,返回一个局部变量,同时defer函数也会操作这个局部变量。对于匿名返回值来说,可以假定仍然有一个变量存储返回值,假定返回值变量为“anony”,上面的返回语句可以拆分成一下过程。 anony = i --> i++ --> return;由于匿名返回值anony的值在defer修改 i 前就已经确定了,所以defer语句中修改i值,对函数返回值不造成影响。