0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

defer的这些坑,你遇到过吗?

马哥Linux运维 来源:马哥Linux运维 2023-12-01 09:28 次阅读

1:延迟函数传递的参数是值


func deferTest() {
  var a = 1
  defer fmt.Println(a)
  
  a = 2
  return
}

结论:延迟函数 fmt.Println(a) 的参数在 defer 语句出现的时候就已经确定下来了,所以不管后面如何修改 a 变量,都不会影响延迟函数

2:延迟函数传递的参数是地址


func deferTest() {
  var arr = [3]int{1, 2, 3}
  defer printTest(&arr)


  arr[0] = 4
  return
}


func printTest(array *[3]int) {
  for i := range array {
    fmt.Println(array[i])
  }
}


结论:延迟函数 printTest() 的参数在 defer 语句出现的时候就已经确定下来了,即为数组的地址,延迟函数执行的时机是在 return 语句之前,所以对数组的最终修改的值会被打印出来。

3:延迟函数可能会影响函数的返回值


fmt.Println(deferTest)


func deferTest() (result int) {
  i := 1
  defer func() {
    result = 2
  }()
  return i
}

结论:函数的 return 语句并不是原子级的,实际的执行过程为为设置返回值—>ret,defer 语句是在返回前执行,所以返回过程是:「设置返回值—>执行defer—>ret」。所以 return 语句先把 result 设置成 i 的值(1),defer 语句中又把 result设置为 2 ,所以最终返回值为 2

4:defer需要定义在panic


func panicBeforeDefer() {
  panic("a")
  defer func() {
    fmt.Println("b")
  }()
}


func panicAfterDefer() {
  defer func() {
    fmt.Println("b")
  }()
  panic("a")
}

结论:代码执行到了painc之后再执行的defer,然后按照defer的先进后出的顺序执行defer,最后才执行panic。那为什么panic时会执行defer,可以看下这段代码就很清楚了。


func gopanic(e interface{}) {
  gp := getg() 
  ...
  
  var p _panic
  p.arg = e
  p.link = gp._panic
  gp._panic = (*_panic)(noescape(unsafe.Pointer(&p)))


  
  for {
    
    d := gp._defer
    if d == nil {
      break
    }
      ...
  }
}

5:先判断err,再defer释放资源


func openFile() {
  file, err := os.Open("txt")
  if err != nil {
    return
  }
  defer file.Close()
}

结论:获取文件资源的时候会返回err,如果我们在后续需要进行defer释放文件资源时,这里需要对err进行判断。因为如果获取文件资源失败的时候不需要进行释放,也避免了没获取到资源可能导致的释放函数执行错误。

6:os.Exit时defer不会被执行


func deferExit() {
  defer func() {
    fmt.Println("exit")
  }()
  os.Exit(1)
}

结论:上面代码中的defer不会得到执行,因为os.Exit()用于立即中止程序,不可能恢复或运行延迟清理语句,不像panic会去找goroutine的defer链表。







审核编辑:刘清

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • defer
    +关注

    关注

    0

    文章

    2

    浏览量

    1111

原文标题:【Golang】defer的这些坑,你遇到过吗?

文章出处:【微信号:magedu-Linux,微信公众号:马哥Linux运维】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    请问大家有没有遇到过这种问题?该怎么解决?

    本人最近做了ADC1的十六路转换,与双ADC的十六路转换,其中测试结果发现个别通道的转换结果要比其他的大一下,大概256左右,0.2V左右,请问大家遇到过这种问题没有?这是什么原因导致呢?如何去解决?大家有什么好的想法和方法不防说出来大家讨论学习一下,谢谢了
    发表于 06-12 03:21

    这些CAD问题遇到过吗?CAD常见问题汇总解答!

    常规的倒圆角制图外,还可以用于绘制平行线相切半圆,这比传统的先画相切圆、再剪切的制图方法快10倍。怎么样这些CAD入门学习过程中常见的问题是不是也遇到过?各位小伙伴在以后学习CAD制图时如果
    发表于 03-05 15:44

    IAP功能实现过程中遇到

    IAP功能实现过程中遇到过哪些?怎样去解决呢?
    发表于 10-25 09:11

    使用openocd下载程序时报错有人遇到过

    clion下使用openocd烧写程序报错在Mac下使用clion开发STM32,在使用openocd下载程序时报错,出现了如下提示,请问有人遇到过吗?在网上找了好多天,都没找到解决方案。
    发表于 01-10 08:28

    是否遇到过某个MCU串口不够的情况

    是否遇到过某个MCU串口不够的情况?这时我们可以考虑用GPIO去模拟,如何具体实现呢?首选我们需要了解串口的传输协议,UART使用异步模式工作,不需要时钟信号,其一般格式为:起始位+数...
    发表于 02-10 06:45

    都知道RK3288编译遇到过哪些问题吗

    都知道RK3288编译遇到过哪些问题吗?
    发表于 03-04 07:22

    用J_link下载程序是遇到的问题,有哪个大佬遇到过,怎么解决的?

    用J_link下载程序是遇到的问题,有哪个大佬遇到过,怎么解决的?
    发表于 02-24 18:31

    请问各位在0使用M0外部晶振时遇到过频率偏低的问题吗?

    请问各位在0使用M0外部晶振时遇到过频率偏低的问题吗?我在最近遇到了使用36MHz晶振时有大约3.3%的片子频率偏低,在2013年8月还遇到过一次,换了晶振和电阻电容都不管用,只有换了M0片子才管用,难道M0震荡部分有缺陷?
    发表于 08-24 06:56

    电瓶修复—电池负极闭孔遇到过没?

    最近啊不管是私信还是在网上很多朋友都问到负极闭孔这个词,还问我电池负极闭孔遇到过没?那么今天就来讲一下我很久之前遇到的这方面问题。 电瓶修复 负极闭孔这是我亲身经历的事情:十年前,我到泉州一个工厂
    的头像 发表于 03-16 10:49 2128次阅读

    PCB设计遇到过孔stub如何解决

    N年的宝贵经验告诉我们,PCB设计遇到过孔stub时,最好办法就是器件在表层走线靠下层,器件在底层走线就靠上层,这样能把stub降到最低。但是,有没有一种种情况,你们觉得无论走哪一层都觉得
    的头像 发表于 03-29 11:16 9326次阅读

    使用Redis时可能遇到哪些「」?

    这篇文章,我想和你聊一聊在使用 Redis 时,可能会踩到的「」。 如果在使用 Redis 时,也遇到过以下这些「诡异」的场景,那很大概率是踩到「
    的头像 发表于 04-09 11:19 2303次阅读
    使用Redis时可能<b class='flag-5'>遇到</b>哪些「<b class='flag-5'>坑</b>」?

    这17种焊接陷阱,遇到过多少?

    良好的焊接是保证电路稳定持久工作的前提。下面给出了常见到的焊接缺陷。看看你遇到过多少种?焊接中的常见问题▲陷阱1:锡珠▲陷阱2:扰动的焊接——在焊接点冷却过程中焊锡移动,造成焊接表面起雾、结晶、粗糙
    的头像 发表于 04-14 09:39 896次阅读
    这17种焊接陷阱,<b class='flag-5'>你</b><b class='flag-5'>遇到过</b>多少?

    这17种焊接陷阱,遇到过多少?

    良好的焊接是保证电路稳定持久工作的前提。下面给出了常见到的焊接缺陷。看看你遇到过多少种?焊接中的常见问题▲陷阱1:锡珠▲陷阱2:扰动的焊接——在焊接点冷却过程中焊锡移动,造成焊接表面起雾、结晶、粗糙
    的头像 发表于 04-14 09:37 812次阅读
    这17种焊接陷阱,<b class='flag-5'>你</b><b class='flag-5'>遇到过</b>多少?

    【广凌房产】高校公用房管理中的这些问题,遇到过吗?

    高校公用房属于国有资产的一部分,但管理过程中遇到各种困难,以下这些问题遇到过吗?
    的头像 发表于 05-30 11:15 504次阅读
    【广凌房产】高校公用房管理中的<b class='flag-5'>这些</b>问题,<b class='flag-5'>你</b><b class='flag-5'>遇到过</b>吗?

    【电路设计】这17种焊接陷阱,遇到过多少?

    良好的焊接是保证电路稳定持久工作的前提。下面给出了常见到的焊接缺陷。看看你遇到过多少种?焊接中的常见问题▲陷阱1:锡珠▲陷阱2:扰动的焊接——在焊接点冷却过程中焊锡移动,造成焊接表面起雾、结晶、粗糙
    的头像 发表于 05-24 09:27 805次阅读
    【电路设计】这17种焊接陷阱,<b class='flag-5'>你</b><b class='flag-5'>遇到过</b>多少?