go 关闭文件句柄_深入理解 Go 语言 defer

本文详细探讨了Go语言中defer的使用,包括return语句的执行过程,defer与闭包的关系,defer的实际应用场景,以及defer的底层实现。通过示例代码和汇编分析,解释了defer如何确保资源的正确释放,特别是在配合recover处理panic时的价值。文中还进行了性能基准测试,展示了defer相对于直接函数调用的开销。
摘要由CSDN通过智能技术生成

f6e40c317630f8699705260884e61a00.png
对 Golang 感兴趣的同学欢迎关注公众号:golang-experts

defer 估计是每个 Gopher 每天写代码都会写,那么你是不是真正的理解了 defer 呢?不妨看一下下面这个代码片段,这个是我之前给 UC 那边一个 team 做 Golang 培训的时候想的例子。

package main

func f() int {
    
    i := 5
    defer func() {
    
        i++
    }()
    return i
}

func f1() (result int) {
     
    defer func() {
     
        result++ 
    }() 
    return 0
}

func f2() (r int) {
     
    t := 5 
    defer func() {
     
        t = t + 5 
    }()
    return t
}

func f3() (r int) {
     
    defer func(r int) {
     
        r = r + 5 
    }(r) 
    return 1
}

func main() {
    
    println(f())
    println(f1())
    println(f2())
    println(f3())
}

1. return 语句

在解析上面的题目之前,要理解一个前提是 Go 的函数返回值是通过堆栈返回的,这也是实现了多返回值的方法。举个例子。

//foo.go
package main

func foo() (int,int){
    
   i := 1
   j := 2
   return i,j
}

func main() {
    
    foo()
}

查看汇编代码如下。

$ go build -gcflags '-l' -o foo foo.go
$ go tool objdump -s "main.foo" foo
TEXT main.foo(SB) /Users/kltao/code/go/src/example/foo.go
  bar.go:6      0x104ea70       48c744240801000000  MOVQ $0x1, 0x8(SP)
  bar.go:6      0x104ea79       48c744241002000000  MOVQ $0x2, 0x10(SP)
  bar.go:6      0x104ea82       c3          RET

也就是说 return 语句不是原子操作,而是被拆成了两步

rval = xxx
ret

而 defer 语句就是在这两条语句之间执行,也就是

rval = xxx
defer_func
ret

另外在 Go 语言的 func 声明中如果返回值变量显示声明,也就是 func foo() (ret int) {} 的时候,rval 就是 ret。这么上面的题目中对于的函数执行简单来说就是如下代码片段。但是 f3 涉及到另外一个知识点,也就是闭包。

//f
rval = i
i ++ 
ret

//f1
result = 0
defer // result ++
return

//f2
r = t
defer // t = t + 5
return

2. 闭包

简单来说,Go 语言中的闭包就是在函数内引用函数体之外的数据,这样就会产生一种结果,虽然数据定义是在函数外,但是在函数内部操作数据也会对数据产生影响。如下面的例子所示,foo() 中的匿名函数对 i 的调用就是闭包引用,i++ 会影响外面定义的 i 的值。而 bar() 中的匿名函数是变量拷贝,i++ 并不会修改外部 i 值。这么看的话,开始的 f3() 的输出你是不是知道是多少了呢?

func foo() {
    
    i := 1
    go func() {<
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值