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在GoLand中引用github.com中的第三方包具体步骤

    Go在GoLand中引用github.com中的第三方包具体步骤

    这篇文章主要给大家介绍了关于Go在GoLand中引用github.com中第三方包的具体步骤,文中通过图文介绍的非常详细,对大家学习或者使用Go具有一定的参考价值,需要的朋友可以参考下
    2024-01-01
  • 一文了解Go语言的并发特性

    一文了解Go语言的并发特性

    本文主要介绍了一文了解Go语言的并发特性,通过轻量级线程、通道及选择语句,使得并发编程变得既简单又高效,下面就来具体了解一下如何使用,感兴趣的可以了解一下
    2024-02-02
  • Golang拾遗之指针和接口的使用详解

    Golang拾遗之指针和接口的使用详解

    拾遗主要是收集和golang相关的琐碎知识,这篇文章主要是为大家整理了Golang中指针和接口的使用方法,文中的示例代码讲解详细,需要的可以参考一下
    2023-02-02
  • 如何使用Golang创建与读取Excel文件

    如何使用Golang创建与读取Excel文件

    我最近工作忙于作图,图表,需要自己准备数据源,所以经常和Excel打交道,下面这篇文章主要给大家介绍了关于如何使用Golang创建与读取Excel文件的相关资料,需要的朋友可以参考下
    2022-07-07
  • go内存缓存BigCache封装Entry源码解读

    go内存缓存BigCache封装Entry源码解读

    这篇文章主要为大家介绍了go内存缓存BigCache封装Entry源码解读,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-09-09
  • go语言实现markdown解析库的方法示例

    go语言实现markdown解析库的方法示例

    这篇文章主要介绍了go语言实现markdown解析库的方法示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-02-02
  • 详解Golang net/http包中的RoundTripper接口

    详解Golang net/http包中的RoundTripper接口

    RoundTripper 是 net/http 包中的一个接口,定义了处理 HTTP 请求返回和响应的方法,是 http.Client 结构体中执行 http 请求的核心部分,本文将详细的给大家介绍Golang RoundTripper接口,需要的朋友可以参考下
    2023-09-09
  • GO实现跳跃表的示例详解

    GO实现跳跃表的示例详解

    跳表全称叫做跳跃表,简称跳表,是一个随机化的数据结构,实质就是一种可以进行二分查找的有序链表。本文将利用GO语言编写一个跳表,需要的可以参考一下
    2022-12-12
  • golang gorm的关系关联实现示例

    golang gorm的关系关联实现示例

    这篇文章主要为大家介绍了golang gorm的关系关联实现示例,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步早日升职加薪
    2022-04-04
  • Go prometheus metrics条目自动回收与清理方法

    Go prometheus metrics条目自动回收与清理方法

    这篇文章主要为大家介绍了Go prometheus metrics条目自动回收与清理方法详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-11-11

最新评论