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 @ 2022-06-25 15:06  wanghhhh  阅读(163)  评论(0)    收藏  举报