浅谈Go的延迟调用、异常处理
在讲Go的延迟地调用defer之前,先聊聊Go的闭包,这是上篇文章函数中没有提到的。
Go闭包
闭包是由函数及其相关引用环境组合而成的实体,用公式表达就是 闭包 = 函数 + 引用环境
百度百科闭包的概念:闭包就是能够读取其他函数内部变量的函数。例如在javascript中,只有函数内部的子函数才能读取局部变量,所以闭包可以理解成“定义在一个函数内部的函数“。在本质上,闭包是将函数内部和函数外部连接起来的桥梁
package main
import (
"fmt"
)
func a() func() int {
i := 0
b := func() int {
i++
fmt.Println(i)
return i
}
return b
}
func main() {
test := a()
test() // 1
test() // 2
test() // 3
a() //不会输出i
}
从上述代码中可以看出,函数b是函数a的内嵌函数,函数a负责返回函数b, 那么变量test接收的就是函数b,执行test() 就会输出i的值,第一次为1,第二次为2,第三次为3...
这段代码就很好展示了什么是闭包,函数a外的变量引用了函数a内部的函数b,这就创建了一个闭包。
由于闭包的创建,函数a中的变量i一直存在,每次执行test(),i都会自增1,那么作用就是当执行完函数a之后,GC不会回收函数a所占用的资源,因为函数b执行需要用到函数a中的变量i
延迟调用defer
讲完了闭包的概念,就回到今天的重点内容延迟调用defer,这个会在异常处理中起到很重要的作用。
defer特性
- defer是关键字,用于申明延迟调用
- 需要等到return前才会执行调用,可以用来清理资源,错误恢复等
- 多个defer语句,采用栈的的入队方式,先进后出
- defer语句的变量,在声明的时候就明确了
defer用途
- 关闭文件句柄
- 释放锁资源
- 数据库、redis连接释放等
package main
import "fmt"
func main() {
var test [5]struct{}
for i := range test {
defer fmt.Println(i)
}
}
输出结果如下:
defer碰上闭包
package main
import "fmt"
func main() {
var test [5]struct{}
for i := range test {
defer func() {
fmt.Println(i)
}()
}
}
输出结果如下:
结果并不是像上面那样输出,因为轮到defer执行的时候,变量i已经变成4了,所以输出的全部都是4
如果运行过程中,延迟调用发生错误,程序会继续执行,按照先进后出的顺序执行,看下面的例子
package main
func test(x int) {
defer println("a")
defer println("b")
defer func() {
println(10 / x) // div0 异常未被捕获,逐步往外传递,最终终止进程。
}()
defer println("c")
}
func main() {
test(0)
}
异常处理
Go语言处理处理异常,使用panic抛出异常,使用recover接收异常
panic
- go内置函数
- 遇到panic函数,会终止后面要执行的语句,存在defer会按照顺序执行
- 直到整个goroutine退出,显示错误
revocer
- go内置函数
- 控制一个goroutine的panicking行为,接收panic异常
- 只有在defer调用的函数中才能生效
以下为例子演示:
package main
import "fmt"
func test() {
defer func() {
if err := recover(); err != nil { //接收异常
fmt.Println(err.(string))
fmt.Println("defer end")
}
}()
fmt.Println("start")
panic("this is a panic!") //抛出异常
fmt.Println("end") //执行不到
}
func main() {
test()
}
由于 panic、recover 参数类型为 interface{},因此可抛出任何类型对象。
func panic(v interface{})
func recover() interface{}
总结
今天简单的学习了Go
的闭包,延迟调用,异常处理,还有很多细节的部分,下一步需要继续深入,对于刚入门go语言的我来说,还有许多地方需要学习,有错误的地方欢迎大家指出,共同进步!!
转载自:https://juejin.cn/post/7169562361127403551