package main import "fmt" func df()int{ i:=5 defer func(){ i = i + 10 fmt.Println("defer函数中的i:",i) }() fmt.Println("df中的i:",i) return i } func main(){ ri := df() fmt.Println(ri) }结果:
package main import "fmt" func df()int{ i:=5 defer func(j int){ j = j + 10 fmt.Println("defer函数中的j:",j) }(i + 1) i=i+30 return i } func main(){ ri := df() fmt.Println(ri) }结果:
package main import "fmt" func df()int{ i:=5 defer func(j int){ j = j + 10 fmt.Println("defer函数1中的j:",j) }(i + 1) defer func(j int){ j = j + 20 fmt.Println("defer函数2中的j:",j) }(i + 1) defer func(j int){ j = j + 30 fmt.Println("defer函数3中的j:",j) }(i + 1) return i } func main(){ ri := df() fmt.Println(ri) }结果:
(1)延迟执行:defer关键字后的函数都是在整个函数执行结束return之后才执行的。正如上述例1代码中最终df函数的返回值是5而不是15,且先执行打印“df中的i”再执行打印“defer函数中的i”所示。上述代码是先执行完df函数中除了defer后面的函数之外的语句。return i(i的值依旧是5)之后,再执行defer后面的函数,执行i = i +10,且打印i
(2)参数预计算:defer函数的形参会在定义时就完成了该参数的拷贝。正如上述例2代码中传入到defer后面函数的形参j的实参i+1不是35,而是6。
(3)FILO:先进后出,若多个defer函数在同一函数内,执行顺序遵循先进后出原理。即第一个defer函数最后一个被执行。正如上述例3代码中第三个defer函数先执行,然后再是第二个defer函数执行,最后再是第一个defer函数执行
type _defer struct{ sp uintptr //函数栈指针 pc uintptr //程序计数器 fn *funcval //函数地址 lnk *_defer //指向自身结构的指针,用于链接多个defer }
(1)defer的创建deferproc():在defer的声明处调用,其将defer函数存于goroutine的链表中
(2)defer的执行deferreturn():在return指令前调用,其将defer函数从链表中取出并执行
(3)可以简单理解为:声明defer处插入了deferproc()函数,在函数return前插入了deferreturn()函数
(1.1)当defer执行完毕,会放入到局部缓存池
(1.2)当局部缓存池容纳足够的对象时,会放到全局缓存池
(1.3)当逻辑处理器的局部缓存池为空时,会从全局缓存池中取一部分放到局部缓存池
(1.4)当对象没有被使用时,会被垃圾回收
(3.1)函数的defer数量小于等于8个
(3.2)函数的defer关键字不能在循环中使用
(3.3)函数的return语句和defer语句的数量的乘积小于等于15个
package main import "fmt" func df()int{ i:=5 defer func(){ i = i + 10 }() return i } func main(){ ri := df() fmt.Println(ri) }
package main import "fmt" func df()int{ i:=5 defer func(){ i = i + 10 fmt.Println("defer函数中的i:",i) }() fmt.Println("df中的i:",i) return i } func main(){ ri := df() fmt.Println(ri) }
结果:
package main import "fmt" func df()(i int){ i = 5 defer func(){ i = i + 10 fmt.Println("defer函数中的i:",i) }() fmt.Println("df中的i:",i) return i } func main(){ ri := df() fmt.Println(ri) }
结果:
package main import "fmt" func main(){ panic("aaaaa") defer func(){ fmt.Println("执行defer") }() }结果:
package main import "fmt" func main(){ defer func(){ fmt.Println("执行defer") }() panic("aaaaa") }结果: