go语言defer panic recover用法总结
defer
defer是go提供的一种资源处理的方式。defer的用法遵循3个原则
- 在defer表达式被运算的同时,defer函数的参数也会被运算。如下defer的表达式println运算的同时,其入参i也会被运算,结果为初始化值0,故defer调用中会打印“0”
1 func a() {
2 i := 0
3 defer fmt.Println(i)
4 i++
5 return
6 }
- defer函数在一个函数return之后遵循后进先出的调用原则,如下打印结果为3210
func b() {
for i := 0; i < 4; i++ {
defer fmt.Print(i)
}
}
- defer函数可能会读取并赋值给所在函数的返回值,如下返回值为2
func c() (i int) {
defer func() { i++ }()
return 1
}
针对上述的第三点有如下三种情况:
例1:
func f() (result int) {
defer func() {
result++
}()
return 0
}
例2:
func f() (r int) {
t := 5
defer func() {
t = t + 5
}()
return t
}
例3:
func f() (r int) {
defer func(r int) {
r = r + 5
}(r)
return 1
}
函数返回的过程是这样的:先给返回值赋值,然后再调用defer表达式,最后才是返回到调用函数中
先看例1,它可以改写成这样:
func f() (result int) {
result = 0 //return语句不是一条原子调用,return xxx其实是赋值+ret指令
func() { //defer被插入到return之前执行,也就是赋返回值和ret指令之间
result++
}()
return
}
所以这个返回值是1。
再看例2,它可以改写成这样:
func f() (r int) {
t := 5
r = t //赋值指令
func() { //defer被插入到赋值与返回之间执行,这个例子中返回值r没被修改过
t = t + 5
}
return //空的return指令
}
所以这个的结果是5。
最后看例3,它改写后变成:
func f() (r int) {
r = 1 //给返回值赋值
func(r int) { //这里改的r是传值传进去的r,不会改变要返回的那个r值
r = r + 5
}(r)
return //空的return
}
所以这个例子的结果是1。
panic和recover
panic和recover的使用需要遵循以下原则:
- defer 需要放在 panic 之前定义,另外recover只有在 defer 调用的函数中才有效。
- recover处理异常后,逻辑并不会恢复到 panic 那个点去,函数跑到 defer 之后的那个点.
- 多个 defer 会形成 defer 栈,后定义的 defer 语句会被最先调用
使用recover捕获程序中的错误的用法如下
package main import (
"fmt"
"time"
) func main() {
f()
fmt.Println("end")
} func f() {
defer func() { //必须要先声明defer,否则不能捕获到panic异常
fmt.Println("defer start")
if err := recover(); err != nil {
fmt.Println(err) //这里的err其实就是panic传入的内容,"bug"
}
fmt.Println("defer end")
}()
for {
fmt.Println("func begin")
a := []string{"a", "b"}
fmt.Println(a[3]) // 越界访问,肯定出现异常
panic("bug") // 上面已经出现异常了,所以肯定走不到这里了。
fmt.Println("func end") // 不会运行的.
time.Sleep(1 * time.Second)
}
}
输出结果如下
func begin
defer start
runtime error: index out of range
defer end
end
注:上述代码摘自如下参考的文档
参考:
go语言defer panic recover用法总结的更多相关文章
- Go语言异常处理defer\panic\recover
Go语言追求简洁优雅,所以,Go语言不支持传统的 try…catch…finally 这种异常,因为Go语言的设计者们认为,将异常与控制结构混在一起会很容易使得代码变得混乱.因为开发者很容易滥用异常, ...
- defer,panic,recover
Go语言不支持传统的 try…catch…finally 这种异常,因为Go语言的设计者们认为,将异常与控制结构混在一起会很容易使得代码变得混乱.因为开发者很容易滥用异常,甚至一个小小的错误都抛出一个 ...
- Go的异常处理 defer, panic, recover
Go语言追求简洁优雅,所以,Go语言不支持传统的 try…catch…finally 这种异常,因为Go语言的设计者们认为,将异常与控制结构混在一起会很容易使得代码变得混乱.因为开发者很容易滥用异常, ...
- defer, panic, recover使用总结
1. defer : 延迟调用.多个defer,依次入栈,在函数即将退出时,依次出栈调用 package main import "fmt" func main() { defer ...
- Go语言 异常panic和恢复recover用法
Go语言 异常panic和恢复recover用法 背景:Go语言追求简洁优雅,所以,Go语言不支持传统的 try…catch…finally 这种异常,因为Go语言的设计者们认为,将异常与控制结构混在 ...
- Golang 入门系列(十四)defer, panic和recover用法
以前讲过golang 的基本语法.但是,只是讲了一些基础的语法,感兴趣的可以看看以前的文章,https://www.cnblogs.com/zhangweizhong/category/1275863 ...
- go panic recover 异常处理
Go语言追求简洁优雅,所以,Go语言不支持传统的 try…catch…finally 这种异常,因为Go语言的设计者们认为,将异常与控制结构混在一起会很容易使得代码变得混乱.因为开发者很容易滥用异常, ...
- go语言 defer 高级
go语言defer语句的用法 defer的语法 defer后面必须是函数调用语句,不能是其他语句,否则编译器会出错. package main import "log" func ...
- [日常] Go语言圣经-Panic异常,Recover捕获异常习题
Go语言圣经-Panic异常1.当panic异常发生时,程序会中断运行,并立即执行在该goroutine中被延迟的函数(defer 机制)2.不是所有的panic异常都来自运行时,直接调用内置的pan ...
随机推荐
- 用eclipes写第一个HelloWorld
打开 eclipes 后,首先点击左上角新建按钮,新建一个项目,如图: 选择 Java Project 选项: 如果没有java Project这个选项的话,选择次一个的 project 也可以,在跳 ...
- android DecorView深入理解
开发中,通常都是在onCreate()中调用setContentView(R.layout.custom_layout)来实现想要的页面布局.页面都是依附在窗口之上的,而DecorView即是窗口最顶 ...
- plx9030触发pci中断
if(((SWAB_16(PLX_INT(0x4C)))&0x04)==0x04) { ErrNo = *(UINT16*)(g_MemBase+0XFFFE*2); /*logMsg(&qu ...
- 【mysql】phpMyadmin上传文件限制
在使用phpMyadmin导入数据库的时候,因为脚本在上传的时候响应时间过长,导致大于2M的数据偶尔会导入失败.而且大多数默认设置,只能导入2M的数据. 遇到这种情况, 我们可以修改php.ini以及 ...
- JavaScript获取屏幕和页面的宽度和高度
JavaScript获取屏幕和页面的宽度和高度 1.设计源码 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN ...
- Java导出防止小数显示不全工具类
1.说明 在做项目的过程中,发现导出功能中的数据显示不全,如"0.4",会显示成".4":"-0.8"会显示成"-.8" ...
- DirectX:函数可以连接任意两个filter
函数可以连接任意两个filter HRESULT ConnectFilters( IBaseFilter *pSrc, IBaseFilter *pDest ) { IPin *pIn = 0; IP ...
- Django学习-20-信号
Django信号 使得某个操作之前能定制化一些任务 - 内置信号 pre_init # django的model执行其构造方法前,自动触发 post_ ...
- hdu5556 Land of Farms
我对于题目的一种理解 改造农场 1.建新农场 在空的点选 2.重建旧农场 选一个点属于这个农场的地方都要选 最后的农场都不能相连 所以枚举旧农场的个数并进行二分图匹配 #include<bits ...
- Matlab和C语言混合编程,包含目录的设定
如果.c文件不依赖于任何第三方库,那么mex编译很简单,只需要在matlab的命令行输入 mex test.c 即可. 但是如果这个c文件使用了第三方库文件,如opencv.gsl等等,那么就需要更改 ...