美文网首页
golang中defer使用小结

golang中defer使用小结

作者: 清晨的麦田 | 来源:发表于2019-07-12 17:18 被阅读0次

golang语言中defer的使用场景较多,用于锁的关闭,连接的延迟关闭等,通常在函数的结束时调用,详细的讲就是在函数结束时返回值赋值后,返回前执行defer的方法,最后才返回,另外defer确实有一定的开销,拒绝滥用。

第一点、defer 不带函数执行,defer可以理解像栈,先进后出,看下面代码

func main() {
    defer fmt.Println("one")  //第一个进入
    defer fmt.Println("two")  //第二进入
    defer fmt.Println("three") //第三个进入
}

按照先进后出的规则输出

three
two
one

Process finished with exit code 0

第二点、defer带函数的执行,defer执行在返回赋值后,返回前执行,看下面的列子

下面的列子,我们定义 一个返回值res=1,然后返回(return)res时,赋值为7,根据我们所讲,defer函数执行在返回赋值后,返回前,那么此时res为7,defer 函数执行将res赋值为8,return最后返回应该为8
看下面代码

package main

import "fmt"
func main() {
    fmt.Println(test())
}

func test() (res int) {
    res = 1
    defer func() {
        fmt.Println("start", res)
        res++
        fmt.Println("end", res)
    }()
    return 7
}

执行结果:

start 7
end 8
8

Process finished with exit code 0

第三点、defer 一定是延迟执行的么?答案是肯定的。但是有注意点需要注意

看下面列子

package main

import "fmt"

type SliceNum []int

func NewSlice() SliceNum {
    return make(SliceNum, 0)

}

func (s *SliceNum) Add(elem int) *SliceNum {
    *s = append(*s, elem)
    fmt.Println("add", elem)
    fmt.Println("add SliceNum end", s)
    return s
}
func (s *SliceNum) test(elem int) *SliceNum {
    fmt.Println("test", elem)
    fmt.Println("test", s)
    return s
}

func main() {
    s := NewSlice()
    defer s.Add(1)
    s.Add(10)

}

输出结果:
此时大家应该想到肯定是切片的加入顺序应该是10 然后 是1 结果也是这样

add 10
add SliceNum end &[10]
add 1
add SliceNum end &[10 1]

Process finished with exit code 0

读者客官可能会说,这太简单了,那么我们在defer 后面连续执行是什么效果呢?
我们修改下main函数执行的方法如下:


func main() {
    s := NewSlice()
    defer s.Add(1).Add(4)
    s.Add(11)
    s.Add(12)
    s.Add(13)
}

大家猜想下?可以先给个答案
看下执行:

add 1
add SliceNum end &[1]
add 11
add SliceNum end &[1 11]
add 12
add SliceNum end &[1 11 12]
add 13
add SliceNum end &[1 11 12 13]
add 4
add SliceNum end &[1 11 12 13 4]

Process finished with exit code 0
此时defer后面的一个方法Add(1)先执行了,然后才执行的s.Add(11),s.Add(12),s.Add(13),最后才执行了Add(4)

defer后面继续执行同样的方法或者其他方法呢?改变下我们的main函数如下:

func main() {
    s := NewSlice()
    defer s.Add(1).Add(4).Add(100).test(200)
    s.Add(11)
    s.Add(12)
    s.Add(13)
}

这个执行结果又是怎么样的?
看下结果吧:

add 1
add SliceNum end &[1]
add 4
add SliceNum end &[1 4]
add 100
add SliceNum end &[1 4 100]
add 11
add SliceNum end &[1 4 100 11]
add 12
add SliceNum end &[1 4 100 11 12]
add 13
add SliceNum end &[1 4 100 11 12 13]
test 200
test &[1 4 100 11 12 13]

Process finished with exit code 0

可以看到defer 中先执行的s.Add(1).Add(4).Add(100),然后执行s.Add(11), s.Add(12),s.Add(13),延迟执行的test函数,可以看到defer延迟执行的是最后的一个函数

如何保证整个defer是在最后执行呢?当然可以了使用 defer fun(){
}(),包住此方法

修改下main函数

func main() {
    s := NewSlice()
    defer func() {
        s.Add(1).Add(4).Add(100).test(200)
    }()//用func(){}()包住
    s.Add(11)
    s.Add(12)
    s.Add(13)
}

输出结果:

add 11
add SliceNum end &[11]
add 12
add SliceNum end &[11 12]
add 13
add SliceNum end &[11 12 13]
add 1
add SliceNum end &[11 12 13 1]
add 4
add SliceNum end &[11 12 13 1 4]
add 100
add SliceNum end &[11 12 13 1 4 100]
test 200
test &[11 12 13 1 4 100]

Process finished with exit code 0

此时,先执行s.Add(11),s.Add(12),s.Add(13),然后执行defer函数中的方法s.Add(1).Add(4).Add(100).test(200),最后输出已经按照我们想要的顺序执行了。

相关文章

  • golang中defer使用小结

    golang语言中defer的使用场景较多,用于锁的关闭,连接的延迟关闭等,通常在函数的结束时调用,详细的讲就是在...

  • Golang之Defer

    引用 golang defer实现原理 Golang之轻松化解defer的温柔陷阱 Golang中defer、re...

  • 2017-12-04

    Golang,Panic,Defer,Recover 在golang中,recover在defer里发挥作用。 一...

  • go defer理解

    golang的defer是怎么工作的?defer在golang里是一个很基础的关键字,在函数内部使用defer声明...

  • golang中defer的使用

    在golang当中,defer代码块会在函数调用链表中增加一个函数调用。这个函数调用不是普通的函数调用,而是会在函...

  • 12 Golang defer panic recover

    defer Golang中的defer会将其后面跟随的语句进行延迟处理。在defer归属的函数即将返回时,将延迟处...

  • golang 延时函数defer 作final处理文件或异常

    golang 延时函数defer 作final处理文件或异常defer 函数先进后出原则,在函数内部使用时,会在r...

  • GO中defer关键字

    defer关键字在go中用于return之前执行,在golang官方文档中有说明。defer的用法类似java中的...

  • Golang中defer用法

    Go语言中的defer语句会将其后面跟随的语句进行延迟处理。在defer归属的函数即将返回时,将延迟处理的语句按d...

  • golang 中的 defer

    defer 是在return 之前执行的但是return xxx 并不是一条原始指令

网友评论

      本文标题:golang中defer使用小结

      本文链接:https://www.haomeiwen.com/subject/hilykctx.html