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),最后输出已经按照我们想要的顺序执行了。