- 数据结构相当于栈,多个defer 倒序执行
- defer语句用于延迟函数的调用,每次defer都会把一个函数压入栈中,函数返回前再把延迟的函数取出并执行defer 语句会在函数 return 后执行,但是它会先保存该语句的参数值,并在函数退出时按 后进先出(LIFO) 的顺序执行。
- defer的执行顺序在return之后,但是在返回值返回给调用方之前,所以使用defer可以达到修改返回值的目的。
看四个题
package go_basic
import (
"fmt"
"testing"
)
func TestDeferReturn2(t *testing.T) {
ret := testReturn2()
fmt.Println("test return:", ret)
}
// 返回值改为命名返回值
func testReturn2() (i int) {
//var i int
defer func() {
i++
fmt.Println("test defer, i = ", i)
}()
return i
}
/*
test defer, i = 1
test return: 1
*/
func TestDeferReturn1(t *testing.T) {
ret := testReturn1()
fmt.Println("test return:", ret)
}
func testReturn1() int {
var i int
defer func() {
i++ //defer里面对i增1
fmt.Println("test defer, i = ", i)
}()
fmt.Println(i)
i = i + 2
return i
}
/*
0
test defer, i = 3
test return: 2
*/
func TestDeferFuncParameter(t *testing.T) {
deferFuncParameter()
}
func deferFuncParameter() {
var aInt = 1
defer fmt.Println(aInt)
aInt = 2
aInt = aInt * 3
return
}
/*
1
*/
func TestDefer(t *testing.T) {
testErr()
}
func testErr() {
var aInt = 1
defer func() {
fmt.Println(aInt)
}()
aInt++
aInt = aInt * 3
return
}
/*
6
*/
总结
- defer定义的延迟函数参数在defer语句出时就已经确定下来了
- defer定义顺序与实际执行顺序相反
- return不是原子操作,执行过程是: 保存返回值(若有)—>执行defer(若有)—>执行ret跳转
- 申请资源后立即使用defer关闭资源是好习惯
评论区