函数defer语句

go语言中的defer语句会将其后面跟随的语句进行延迟处理。在defer归属的函数即将返回时,将延迟处理的语句按defer定义的逆序进行执行,也就是说,先被defer的语句最后被执行,最后被defer的语句最先被执行

举个例子

正常声明一个函数

import "fmt"

func deferdemo() {
  fmt.Println("start")
  fmt.Println("1")
  fmt.Println("2")
  fmt.Println("3")
  fmt.Println("end")
}
func main() {
  deferdemo()
}

打印的结果为:

[Running] go run "g:\go\practice\deferdemo\main.go"
start
1
2
3
end

给123加上defer后的代码为:

import "fmt"

func deferdemo() {
  fmt.Println("start")
  defer fmt.Println("1")
  defer fmt.Println("2")
  defer fmt.Println("3")
  fmt.Println("end")
}
func main() {
  deferdemo()
}

打印的结果为:

[Running] go run "g:\go\practice\deferdemo\main.go"
start
end
3
2
1

由此可知

使用了defer参数的字段会在函数执行完成后再执行拥有defer参数的字段,还是从函数末尾开始执行

什么时候会使用

多用于函数结束之前释放资源(文件句柄,数据库连接,socker连接)

一个面试题

package main

import "fmt"

//go语言中return不是原子操作性,再底层是分为两步执行
//第一步:返回值赋值
//defer
//第二步:真正的RET返回
//函数中如果存在defer,那么defer执行的时机是在第一步和第二步之间

func f1() int {
  x := 5
  defer func() {
    x++ // 修改的x不是返回值
  }()
  return x //返回的值为5,因为没有定义返回值参数,所以返回的这个x是新定义的参数
}

func f2() (x int) {
  defer func() {
    x++
  }()
  return 5 //因为返回值为x,defer在返回前执行了x++所以返回值为6
}

func f3() (y int) {
  x := 5
  defer func() {
    x++
  }()
  return x //y := x := 5 ,值为5,后面x加一也和y没有关系了
}

func f4() (x int) {
  defer func(x int) {
    x++ //这里相当于一个副本
  }(x) //这里相当一吧x=5作为参数再次传入defer函数中
  return 5 //返回值为5
}

func main() {
  fmt.Println(f1())
  fmt.Println(f2())
  fmt.Println(f3())
  fmt.Println(f4())
}

例子

package main

import "fmt"

func calc(index string, a, b int) int {
  ret := a + b
  fmt.Println(index, a, b, ret)
  return ret
}

func main() {
  a := 1
  b := 2
  defer calc("1", a, calc("10", a, b)) //后面calc()因为返回值是int所以可以这样调用
  a = 0
  defer calc("2", a, calc("20", a, b)) //后面calc()因为返回值是int所以可以这样调用
  b = 1
}

// 1. a=1
// 2. b=2
// 3. defer calc("1",1, calc("10",1,2))
// 4. calc("10",1,2) //计算出它的结果 RET= a +b RET = 3 并输出内容fmt.Println("10", 1, 2, 3)
// 5. defer calc("1",1,3) //目前只保存,不运算并输出结果
// 6. a = 0
// 7. defer calc("2" , 0 ,calc("20", 0, 2))
// 8. calc("2", 0, 2) //计算出它的结果 RET= a +b RET = 2 并输出内容fmt.Println("20", 0, 2, 2)
// 9. defer calc("2",0,2) //目前只保存,不运算并输出结果
// 10. b=1
// 11.calc("2",0,2) //计算并输出结果 RET = a+b RET = 2 输出结果fmt.Println("2",0,2,2)
// 12.calc("1",1,3) //计算并输出结果 RET = a+b RET = 4 输出结果fmt.Println("1",1,3,4)

/* 整体输出为:
10 1 2 3
20 0 2 2
2 0 2 2
1 1 3 4
*/


defer语句在执行到其时会先向defer语句内的变量赋值,如果赋值过程中有计算过程会计算赋值,当程序执行完成后再进行运算,输出

posted @   suknna  阅读(22)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
点击右上角即可分享
微信分享提示