1.defer是什么?
defer
是Golang中的一个关键字,用来修饰函数,被defer
修饰的函数会被延时执行。
当一个函数调用前有关键字 defer
时, 那么这个函数的执行会推迟到包含这个 defer
语句的函数
在返回 / 结束 / 对应的goroutine发生panic的时候。
2.defer的作用?
3.defer的使用
func main() {
defer fmt.Printf("%v\n", "last")
fmt.Printf("%v\n", "first")
fmt.Printf("%v\n", "second")
}
first
second
last
总结:被defer
关键字修饰的函数(Printf函数)执行时机会在包含这个 defer
语句的函数 (main函数)在返回/结束时候执行。
func main() {
m := 1
defer fmt.Printf("x=%v\n", m)
m++
fmt.Printf("y=%v\n", m)
}
y=2
x=1
func main() {
m := 1
defer func(m int) {
fmt.Printf("x=%v\n", m)
}(m)
m++
fmt.Printf("y=%v\n", m)
}
x=2
y=1
总结:通过defer
修饰的函数,这个函数的参数值在defer
的时候就被确定了。
但是:defer
函数内部所使用的变量值是外部函数运行结束后的值。如下案例3
案例3:
func main() {
m := 1
defer func() {
fmt.Printf("x=%v\n", m)
}()
m++
fmt.Printf("y=%v\n", m)
}
y=2
x=2
案例4:
func main() {
m := 1
defer fmt.Printf("x=%v\n", m)
defer fmt.Printf("y=%v\n", m)
fmt.Printf("z=%v\n", m)
}
z=1
y=1
x=1
总结:defer
关键字声明的函数执行顺序遵循栈结构(后进先出)。
通俗解释:defer
声明的函数会依次压入到栈中,在它的外部函数执行结束后,开始弹栈,所以y=1会比x=1先打印。
4.defer和return的执行顺序 (重点)
案例5:
func main() {
fmt.Printf("z=%v\n", test())
}
func test() int { //无名返回值
i := 0
defer func() {
i++
}()
return i //z=0
}
案例6:
func main() {
fmt.Printf("z=%v\n", test())
}
func test() (i int) { //有名返回值
defer func() {
i++
}()
return i //z=1
}
通过上面两个例子,我们可以看到:被调用函数的返回值声明为int
和(i int)
,两者的返回值是不一样的。
要解决这个疑惑,我们需要知道:return
是非原子操作,包括赋值、返回值两步。而defer
、return
的执行顺序是:return
执行第一步,把结果写入返回值中(赋值);然后执行defer
定义的函数内容;最后return
执行第二步进行数值返回操作(返回值)。
解释实例5:
return
时会默认指定一个返回值(假设为j),将i赋值给j,即i=j=0;defer
操作会对i进行+1,但这个操作与j无关,所以j依旧为0;解释实例6:
(i int)
定义中的i变量;总结:出现案例5和案例6返回值不同的原因是Golang底层对函数无名返回值和有名返回值的处理机制是不一样的。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。