go 之 defer, panic 和 recover
Defer
defer用于当前一个方法或者函数的延迟执行(或者当前所创建的匿名函数),他会在外围函数或者方法返回之前执行, 如果存在多个defer的话, 它比较符合LIFO(先进后出)的顺序执行。类似于析构函数的感觉
一个常用的场景, 就是文件操作的时候
var file *os.File
var err error
if file, err = os.Open(filename); err != nil {
log.Println("file open faild", err)
return
}
defer os.Close() //这个值将在回收之前释放资源
来看一个实际可行的例子
func main() {
fmt.Println("start")
time.Sleep(time.Second * 2)
defer func() {fmt.Println("first")}()
defer func() {fmt.Println("second")}()
defer func() {fmt.Println("three")}()
return
}
start
//两秒后, 这里就符合了LIFO的顺序
three
second
first
Panic 和 Recover
通过内置的panic和recover函数。 GO提供了一套异常处理机制。GO语言将异常和错误是区别对待的, 错误是指可能出错的东西, 程序要以优雅的方法将它处理了, 可是异常是指 "不可能"发生的事儿,例如 true 永远不可能为false。
如果你自己写入了扩展包的话, 其实不推荐使用panic的, 还是以error形式返回比较好, 除非逼不得已必须使用, 必须要让程序立即中断, 但这个时候一般就会在控制台打印出错误, 为了能够优雅的捕获panic的信息, 就必须使用recover,下面看一个简单的例子
func created(start int) int {
if (start > 1) {
return start
}
panic("wrong")
}
func lala(start int) int {
if start > 1 {
return start
}
panic("this is not right")
}
func main() {
defer func() {
if e := recover(); e!=nil {
fmt.Println(e)
}
}()
fmt.Println(created(2))
lala(1)
fmt.Println("continue")
return
}
2
this is not right // 输出
为了能够优雅的捕获panic错误, 这里就必须用defer和recover来进行捕获打印。但是整个程序还是会被终端的, 所以你看不到"continue"这个字符串。这里要提一点的是, defer必须放在前面, 虽然他是符合LIFO的, 但是不要忘了程序是顺序执行的。这里就做一下简单的介绍。
本作品采用《CC 协议》,转载必须注明作者和本文链接