deferreturn
先看一个基础的例子,了解一下defer的效果
func main() {
fmt.Println("in main func:", foo())
}
func foo() int {
i := 0
defer fmt.Println("in defer :", i)
i = 1000
fmt.Println("in foo:", i)
return i+24
}
这段代码运行后会打印出
in foo: 1000
in defer : 0
in main func: 1024
i0deferfmt.Printlnreturnmainfoo
有什么用途?
函数中会申明使用很多变量资源,函数结束时,我们通常会对它们做一些处理:销毁、释放(例如数据库链接、文件句柄、流)。
return
returnreturn
defer
func foo(i int) int {
if i > 100 {
fmt.Println("不是期待的数字")
return 0
}
if i < 50 {
fmt.Println("不是期待的数字")
return 0
}
return i
}
使用defer后,代码可以这样写
func foo(i int) int {
defer func() {
fmt.Println("不是期待的数字")
}()
if i > 100 {
return 0
}
if i < 50 {
return 0
}
return i
}
一个函数中多个defer的执行顺序是什么?
defer
defer
为什么呢 ?
deferdefer
deferdefer
所以,Go语言设计defer的时候是按先进后出的顺序执行的。
例子:
func foo() {
i := 0
defer func() {
i--
fmt.Println("第一个defer", i)
}()
i++
fmt.Println("+1后的i:", i)
defer func() {
i--
fmt.Println("第二个defer", i)
}()
i++
fmt.Println("再+1后的i:", i)
defer func() {
i--
fmt.Println("第三个defer", i)
}()
i++
fmt.Println("再+1后的i:", i)
}
运行后可以看到
+1后的i: 1
再+1后的i: 2
再+1后的i: 3
第三个defer 2
第二个defer 1
第一个defer 0
defer
当传递参数给defer指定的函数时,函数延迟执行,那么参数值会是多少?
网上有一些总结是说:defer指定的函数的参数在 defer 时确定,但,这只是一个总结,真正的原因是, Go语言除了map、slice、chan都是值传递。
改造一下上面这个例子
func foo() {
i := 0
defer func(k int) {
fmt.Println("第一个defer", k)
}(i)
i++
fmt.Println("+1后的i:", i)
defer func(k int) {
fmt.Println("第二个defer", k)
}(i)
i++
fmt.Println("再+1后的i:", i)
defer func(k int) {
fmt.Println("第三个defer", k)
}(i)
i++
fmt.Println("再+1后的i:", i)
}
得到的结果
+1后的i: 1
再+1后的i: 2
再+1后的i: 3
第三个defer 2
第二个defer 1
第一个defer 0
ii3
returnreturn
returnreturn
传递指针参数会是什么情况?
deferdefer
改造一下代码:
func foo() {
i := 0
defer func(k *int) {
fmt.Println("第一个defer", *k)
}(&i)
i++
fmt.Println("+1后的i:", i)
defer func(k *int) {
fmt.Println("第二个defer", *k)
}(&i)
i++
fmt.Println("再+1后的i:", i)
defer func(k *int) {
fmt.Println("第三个defer", *k)
}(&i)
i++
fmt.Println("再+1后的i:", i)
}
运行后得到
+1后的i: 1
再+1后的i: 2
再+1后的i: 3
第三个defer 3
第二个defer 3
第一个defer 3
defer会影响返回值吗?
deferfoomainmain
这还是因为相同的原则 Go语言除了map、slice、chan都是值传递
foo1foo2
func main() {
fmt.Println("foo1 return :", foo1())
fmt.Println("foot return :", foo2())
}
func foo1() int {
i := 0
defer func() {
i = 1
}()
return i
}
func foo2() map[string]string {
m := map[string]string{}
defer func() {
m["a"] = "b"
}()
return m
}
运行后,打印出
foo1 return : 0
foot return : map[a:b]
两个函数不同之处在于的返回值的类型,foo1中,int类型return后,defer不会影响返回结果,但是在foo2中map类型是引用传递,所以defer会改变返回结果。
map、slice、chanreturndefer
returndefer
foo1i
func foo1() (i int) {
i = 0
defer func() {
i = 1
}()
return i
}
再运行,可以看到 :
foo1 return : 1
defer
defer在panic和recover处理上的使用
deferrecover
panicpanicrecoverpanicrecoverpanicrecoverpanicpanicdeferrecoverdeferdefer
例如:
func panicfunc() {
defer func() {
fmt.Println("before recover")
recover()
fmt.Println("after recover")
}()
fmt.Println("before panic")
panic(0)
fmt.Println("after panic")
}
运行后,打印出:
before panic
before recover
after recover
总结以下
returnpanic/recover
欢迎关注公众号《晓代码》,和大家一起学习编程吧!