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 }