go语言的try方式-defer

一. defer概述

 defer用来声明一个延迟函数,把这个函数放入到一个栈上,当外部的包含方法return之前,返回参数到调用方法之前调用,也可以说是运行到最外层方法体时调用。我们经常用他来做一些资源的释放,比如关闭io操作。

defer是golang的一个特色功能,被称为“延迟调用函数”。当外部函数返回后执行defer。类似于其他语言的 try… catch … finally… 中的finally,当然差别还是明显的。在使用defer之前我们应该多了解defer的特性,这样才能避免使用上的误区。

 

二. python的try

finally有一些细节我们需要知道 就有了第一个印象:finally会在return之后运行
事实上并非如此
原因: 实际上finally是在return之前调用的
finally中是可以return的 而且这个地方一旦有了return就会覆盖原本的return

 

三. 注意

1. defer之后只能是函数调用 不能是表达式 比如 a++

2. 多个defer是按照先进后出的顺序执行

3.defer的拷贝机制

示例一: 

func main() {
//defer语句执行时的拷贝机制
test := func() {
fmt.Println("test1")
}
defer test()
test = func() {
fmt.Println("test2")
}
fmt.Println("test3")
}

输出结果:

test3
test1

疑问:为什么先执行test3,而后去执行test1呢, 而不是test2

因为,在压栈的时候是压的一个函数,取的时候也是取的整个函数

 

示例二:

func main() {
//defer语句执行时的拷贝机制
x := 10
defer func (a *int) {
fmt.Println(*a)
}(&x)
x++
}

输出:10

但是为什么是10,不是11呢?

因为要压栈的不仅仅是函数,还要把值压进来

 

示例三:

func main() {
//defer语句执行时的拷贝机制
x := 10
defer func(a *int) {
fmt.Println(x)
}(&x)
x++
}

输出:11

为神马又是11了呢?

因为打印的时候,是取的内存地址取值打印的 ,内存地址的值被修改成11了, 所以defer打印出来的内存地址的值就是11

 

示例四:

func main() {
//defer语句执行时的拷贝机制
x := 10
defer func() {
fmt.Println(x)
}()
x++
}

输出:11

为什么又是11了呢?

压栈的时候其实是没有参数的, 压栈的时候压函数进来,但是函数里面逻辑指向了x,其实指向的是x的这个变量,并不是里面的值,因为defer是在reture最后才执行,所以x++之后执行, x++将值修改成了11,所以打印的为11。函数内部使用的值是全局的值

 

示例五:

func f1() int {
x := 10
defer func() {
x++
}()
tmp := x //x是int类型 值传递
return tmp
}
func f2() *int {
a := 10
b := &a
defer func() {
*b++
}()
temp_data := b
return temp_data
}
func main() {
fmt.Println(f1()) //是不是就意味着 defer中影响不到外部的值呢
fmt.Println(*f2())
}

输出:

10

11

因为x是int类型 值传递,所以传递进去怎么处理,并不影响返回值。 指针反之

 

 

四. 代码说明

 

package main
import "fmt"
//func main() {
// fmt.Println("test1")
// //defer之后只能是函数调用 不能是表达式 比如 a++
// defer fmt.Println("defer test1")
// defer fmt.Println("defer test2")
// defer fmt.Println("defer test3")
// /*
// defer 语句是go体用的一种用于注册延迟调用的机制, 它可以让当前函数执行完毕之后执行
// 对于python的with语句来说,
// */
// //此处有大量的逻辑需要读取文件
// fmt.Println("test2")
// //1. 如果有多个defer会出现什么情况 多个defer是按照先入后出的顺序执行
//}
//func main() {
// //defer语句执行时的拷贝机制
// test := func () {
// fmt.Println("test1")
// }
// defer test()
// test = func () {
// fmt.Println("test2")
// }
// fmt.Println("test3")
//}
//func main() {
// //defer语句执行时的拷贝机制
// x := 10
// defer func (a *int) {
// fmt.Println(*a)
// }(&x)
// x++
//}
//func main() {
// //defer语句执行时的拷贝机制
// x := 10
// //此处的defer函数并没有参数,函数内部使用的值是全局的值
// defer func (a int) {
// fmt.Println(x)
// }(x)
// x++
//}
func f1() int {
x := 10
defer func() {
x++
}()
tmp := x //x是int类型 值传递
return tmp
}
func f2() *int {
a := 10
b := &a
defer func() {
*b++
}()
temp_data := b
return temp_data
}
func main() {
fmt.Println(f1()) //是不是就意味着 defer中影响不到外部的值呢
fmt.Println(*f2())
//defer本质上是注册了一个延迟函数,defer函数的执行顺序已经确定
//defer 没有嵌套 defer的机制是要取代try except finally
//https://www.cnblogs.com/zhangboyu/p/7911190.html
//https://studygolang.com/articles/24044?fr=sidebar
}

 

posted @   wanghhhh  阅读(153)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 零经验选手,Compose 一天开发一款小游戏!
· 一起来玩mcp_server_sqlite,让AI帮你做增删改查!!
点击右上角即可分享
微信分享提示