教程集 www.jiaochengji.com
教程集 >  Golang编程  >  golang教程  >  正文 Go关键字defer的特性

Go关键字defer的特性

发布时间:2022-12-17   编辑:jiaochengji.com
教程集为您提供Go关键字defer的特性等资源,欢迎您收藏本站,我们将为您提供最新的Go关键字defer的特性资源

Go里面,流程控制语句中有一个defer的关键字,翻译过来就是延迟的意思。
下面用代码说话。

func deferFunc() {
    defer fmt.Println("后打印")
    fmt.Println("先打印")
}

defer在函数执行完毕之后,才会执行,所以,我们经常在释放资源或异常处理等需要收尾的场景下会用到defer

不过defer也有一些“坑”,大家需要注意一下。

func printNumbers() {
    for i := 0; i < 5; i   {
        defer func() {
            fmt.Print(i) // 输出55555
        }()
    }
}

上面例子中,defer是在for循环全部执行完毕之后才会执行,所以i已经变成了5,正确做法是下面这样

func printNumbers() {
    for i := 0; i < 5; i   {
        defer func(j int) {
            fmt.Print(j) // 输出43210
        }(i)
    }
}

上面打印的是倒序,这是因为defer的执行顺序和栈的特性一样,都是先进后出

defer还有一个特性,当函数有参数传入时,那些参数的值会在声明时求出

func printNumbers() {
    for i := 0; i < 5; i   {
        defer func(j int) {
            fmt.Print(j) // 输出86420
        }(i * 2)
    }
}

上面的例子大家可能看的不是很清楚,下面给过一个例子

func main() {
    i := 2
    defer fmt.Println(i) // 输出2,原因就是上面说的

    i = 8
    fmt.Println(i)
}

上面这个例子就很明显了,后面i如何变都不会影响defer输出的内容

defer还有一个经常在面试中提到的问题,就是和return的执行顺序,下面是我整理的3个例子

func main() {
    fmt.Println("a return: ", a())
    fmt.Println("b return: ", b())
    fmt.Println("c return: ", *c())
}

func a() int {
    var i int

    defer func() {
        i = 1
        fmt.Println("a defer i: ", i)
    }()

    return i
}

func b() (i int) {
    defer func() {
        i = 2
        fmt.Println("b defer i: ", i)
    }()

    return i
}

func c() *int {
    var i int
    defer func() {
        i = 3
        fmt.Println("c defer i: ", i)
    }()

    return &i
}
// 输出
a defer i:  1
a return:  0
b defer i:  2
b return:  2
c defer i:  3
c return:  3

原因网上有很多优秀的解释,我就再说一下我的理解

  • a函数之所以返回0,是因为返回值是无名的,returni的值写入返回值后,defer再修改i的值,但是已经影响不到返回值了
  • b函数之所以返回1,是因为返回值已经声明成i了,return之后,deferi修改自然就影响了return的返回值了
  • c函数结果和a函数不一样,是因为返回值是指针类型,一样的道理,返回值改不了,但是返回值指向的值已经更改,所以就有上面的结果

正常工作里面,虽然不可能写这种代码,但是面试的时候这些基础问题出现的频率还是挺高的,所以大家也是需要掌握一下。融汇贯通,自己多操作多试试,加深印象。


到此这篇关于“Go关键字defer的特性”的文章就介绍到这了,更多文章或继续浏览下面的相关文章,希望大家以后多多支持JQ教程网!

您可能感兴趣的文章:
Golang defer解读
golangdefer特性姿势还是有必要了解下的!!!
defer函数参数求值简要分析
详解defer实现机制(附上三道面试题)
Golang 学习笔记:流程控制
golang的defer机制详解
Go语言学习3----Go语言特色
golang学习笔记(二)—— 深入golang中的协程
Go语言发展历史、核心、特性及学习路线
Golang中defer关键字实现原理

[关闭]
~ ~