函数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语句内的变量赋值,如果赋值过程中有计算过程会计算赋值,当程序执行完成后再进行运算,输出
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具