golang defer执行顺序全面详解

 更新时间:2023年09月27日 11:19:09   作者:werbenhu  
这篇文章主要为大家介绍了golang defer执行顺序全面详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

defer的执行顺序

多个defer是一个的结构,是先进后出,下面这个代码的输出顺序是CBA。

package main
import "fmt"
func main() {
    defer func1()
    defer func2()
    defer func3()
}
func func1() {
    fmt.Println("A")
}
func func2() {
    fmt.Println("B")
}
func func3() {
    fmt.Println("C")
}

defer和return的顺序

先执行return,再执行defer。

package main
import "fmt"
func deferFunc() {
    fmt.Println("defer func called")
}
func returnFunc() int {
    fmt.Println("return func called")
    return 0
}
func returnAndDefer() int {
    defer deferFunc()
    return returnFunc()
}
func main() {
    returnAndDefer()
}
// output:
// return func called 
// defer func called

函数命名返回值遇见defer

package main
import "fmt"
func foo() (t int) {
    defer func() {
        t = t * 10
    }()
    return 1
}
func main() {
    fmt.Println(foo())
}
// output: 10

defer和panic

panic阻断defer

import (
    "fmt"
)
func deferFn() {
    defer func() { fmt.Println("defer before panic 1") }()
    defer func() { fmt.Println("defer before panic 2") }()
    panic("exit")
    defer func() { fmt.Println("defer after panic") }()
}
func main() {
    deferFn()
    fmt.Println("main exit")
}
/*
output:
defer before panic 2
defer before panic 1
panic: exit
...
*/

defer里面的recover

defer在panic 后依然有效

package main
import (
    "fmt"
)
func deferFn() {
    defer func() {
        fmt.Println("defer before panic 1")
        if err := recover(); err != nil {
            fmt.Println(err)
        }
    }()
    defer func() { fmt.Println("defer before panic 2") }()
    panic("panic info")
    defer func() { fmt.Println("defer after panic") }()
}
func main() {
    deferFn()
    fmt.Println("main exit")
}
/*
output:
defer before panic 2
defer before panic 1
panic info
main exit
*/

defer中包含panic

panic仅有最后一个可以被revover捕获

package main
import (
    "fmt"
)
func main() {
    defer func() {
        if err := recover(); err != nil {
            fmt.Println(err)
        } else {
            fmt.Println("defer call")
        }
    }()
    defer func() {
        panic("defer panic")
    }()
    panic("main panic")
}
// output: defer panic

defer中函数有参数和包含子函数

package main
import "fmt"
func foo(index int, value int) int {
    fmt.Println(index)
    return index
}
func main() {
    defer foo(1, foo(3, 0))
    defer foo(2, foo(4, 0))
}
// output: 3 4 2 1

测试练习

package main
import "fmt"
func DeferFunc1(i int) (t int) {
    t = i
    defer func() {
        t += 3
    }()
    return t
}
func DeferFunc2(i int) int {
    t := i
    defer func() {
        t += 3
    }()
    return t
}
func DeferFunc3(i int) (t int) {
    defer func() {
        t += i
    }()
    return 2
}
func DeferFunc4() (t int) {
    defer func(i int) {
        fmt.Println(i)
        fmt.Println(t)
    }(t)
    t = 1
    return 2
}
func main() {
    fmt.Println(DeferFunc1(1))
    fmt.Println(DeferFunc2(1))
    fmt.Println(DeferFunc3(1))
    DeferFunc4()
}

以上就是golang defer执行顺序全面详解的详细内容,更多关于golang defer执行顺序的资料请关注脚本之家其它相关文章!

相关文章

  • 一文带你掌握Go语言并发模式中的Context的上下文管理

    一文带你掌握Go语言并发模式中的Context的上下文管理

    在 Go 的日常开发中,Context 上下文对象无处不在,无论是处理网络请求、数据库操作还是调用 RPC 等场景,那你真的熟悉它的正确用法吗,随着本文一探究竟吧
    2023-05-05
  • 提升编程技能:学习如何在Go语言中正确格式化时间

    提升编程技能:学习如何在Go语言中正确格式化时间

    想知道如何在Go语言中轻松地格式化时间吗?别再浪费时间了!本文将带你快速入门,让你的代码更加优雅高效,快来学习吧!
    2024-01-01
  • Go语言报错:'godoc' 不是内部或外部命令,也不是可运行的程序(godoc无法使用处理)解决方法

    Go语言报错:'godoc' 不是内部或外部命令,也不是可运行的程序(godoc无法使用处理)解决

    这篇文章主要介绍了Go语言报错:'godoc' 不是内部或外部命令,也不是可运行的程序(godoc无法使用处理)解决方法,详细描述了Go语言godoc命令无法使用的原因、解决方法与相关注意事项,需要的朋友可以参考下
    2024-01-01
  • Go语言中如何实现并发

    Go语言中如何实现并发

    Go的并发机制通过协程和通道的简单性和高效性,使得编写并发代码变得相对容易,这种并发模型被广泛用于构建高性能的网络服务、并行处理任务和其他需要有效利用多核处理器的应用程序,这篇文章主要介绍了在Go中如何实现并发,需要的朋友可以参考下
    2023-09-09
  • golang编程入门之http请求天气实例

    golang编程入门之http请求天气实例

    这篇文章主要介绍了golang编程入门之http请求天气实例,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-08-08
  • 使用Go语言进行安卓开发的详细教程

    使用Go语言进行安卓开发的详细教程

    本文将介绍如何使用Go语言进行安卓开发,我们将探讨使用Go语言进行安卓开发的优点、准备工作、基本概念和示例代码,通过本文的学习,你将了解如何使用Go语言构建高效的安卓应用程序,需要的朋友可以参考下
    2023-11-11
  • go+react实现远程vCenter虚拟机管理终端方式

    go+react实现远程vCenter虚拟机管理终端方式

    基于Go和React实现远程vSphere vcenter虚拟机终端console页面,提供与vcenter管理中的LaunchWebConsole相同的功能,项目包括前端、后端配置,以及vCenter宿主机的Nginx代理设置
    2026-04-04
  • 简单聊聊Golang中defer预计算参数

    简单聊聊Golang中defer预计算参数

    在golang当中defer代码块会在函数调用链表中增加一个函数调用,下面这篇文章主要给大家介绍了关于Golang中defer预计算参数的相关资料,文中通过实例代码介绍的非常详细,需要的朋友可以参考下
    2022-03-03
  • 源码剖析Golang中map扩容底层的实现

    源码剖析Golang中map扩容底层的实现

    之前的文章详细介绍过Go切片和map的基本使用,以及切片的扩容机制。本文针对map的扩容,会从源码的角度全面的剖析一下map扩容的底层实现,需要的可以参考一下
    2023-03-03
  • 详解Go语言中数组,切片和映射的使用

    详解Go语言中数组,切片和映射的使用

    Arrays (数组), Slices (切片) 和 Maps (映射) 是常见的一类数据结构。这篇文章将为大家详细介绍一下Go语言中数组,切片和映射的使用,感兴趣的可以学习一下
    2022-07-07

最新评论