一 函数中间使用defer
func returnValues() int {
var result int
defer func() {
result++
fmt.Println("defer")
}()
return result
}
func nameReturnValue() (result int) {
defer func(){
result++
fmt.Println("defer")
}()
return result
}
// 在这里上面的方法输出0,下面的方法输出1,因为上面使用的匿名返回值,下面使用的命名返回值
// defer的执行逻辑(匿名返回值为例)
1. 将result赋值给返回值,相当于go自动创建一个返回值returnValue,然后将result赋值给returnValue
2. 检查defer,
3. 返回刚刚创建的returnValue
再来看几个demo
func f() (result int) {
defer func() {
result++
}()
return 0
}
func f2() (r int) {
t := 5
defer func() {
t = t + 5
}()
return t
}
func f3() (r int) {
defer func(r int) {
r = r + 5
}(r)
return 1
}
func f4() (r int) {
defer func() {
r = r + 5
}()
return 1
}
// 这里最后的结果是1,5, 1, 6
// f()相当于
func f() (result int) {
var result = 0
func() {
result++ // 1
}()
return
}
// f2()相当于
func f2() (r int) {
t := 5
r = t
func() {
t = t + 5
}()
return
}
r已经赋值无论如何变更t,r的值都不会再次发生改变
// f3()相当于
func f() (r int) {
r = 1 //给返回值赋值
func(r int) { //这里改的r是传值传进去的r,不会改变要返回的那个r值
r = r + 5
}(r)
return //空的return
}
// f4()相当于
func f4() (r int) {
var r = 1
func() {
r = r + 5 // 6
}()
return
}
二 for循环中间使用defer
func deferInLoops(){
for i:=0;i<100;i++{
f, _:= os.Open("xxx")
defer f.Close()
}
}
// 这里需要注意defer的执行是需要额外的开销的,对其后需要的参数进行内存拷贝,还需要对defer结构进行压栈出栈操作
三 判断执行没有err之后,再defer释放资源
resp, err := http.Get(url)
// 先判断操作是否成功
if err != nil {
return err
}
// 如果操作成功,再进行Close操作
defer resp.Body.Close()
四 调用os.Exit的时候defer不会被执行
func deferExit() {
defer func() {
fmt.Println("defer")
}()
os.Exit(0)
}
// 这种情况defer不会被执行
有疑问加站长微信联系(非本文作者)