Go defer panic recover
本文最后更新于:13 天前
1 defer 语句
Go 语言中的defer 语句会将其后面跟随的语句进行延迟处理,在defer语句的函数即将返回时候,将延迟处理的语句按照defer语句的逆序进行执行,也就是说,先被defer的语句最后被执行,最后被defer的语句,最先被执行
1.1 defer 使用
package main
import "fmt"
func main() {
fmt.Println("start")
defer fmt.Println(1)
defer fmt.Println(2)
defer fmt.Println(3)
defer fmt.Println(4)
fmt.Println("over")
}
/*
start
over
4
3
2
1
*/
1.2 defer 命名返回值和匿名返回值
package main
import "fmt"
//调用方法 返回的值是0 : 匿名返回值
func f2() int {
var a int
defer func() {
a++
}()
return a
}
//调用方法 返回的值是1 : 命名返回值
func f3() (a int) {
defer func() {
a++
}()
return a
}
func main() {
fmt.Println(f2())
}
1.3 defer 不太好理解的案例
package main
import "fmt"
func calc(index string,a,b int) int {
ret := a + b
fmt.Println(index,a,b,ret)
return ret
}
//defer: defer在注册要延迟执行的函数时候, 该函数所有的参数都需要确定其值
func main() {
a := 1
b := 2
defer calc("addA",a,calc("A",a,b))
a = 10
defer calc("addB",a,calc("B",a,b))
b = 20
}
/*
注册顺序
defer calc("addA",a,calc("A",a,b))
defer calc("addB",a,calc("B",a,b))
执行顺序
defer calc("addB",a,calc("B",a,b))
defer calc("addA",a,calc("A",a,b))
*/
// 1. calc("A",a,b) A 1 2 3
// 2. calc("B",a,b) B 10 2 12
// 3. calc("addB",a,calc("B",a,b)) addB 10 12 22
// 4. calc("addA",a,calc("A",a,b)) addA 1 3 13 在addA之前定义了a:=1 所以函数参数已经注册生效
2 panic
panic 可以在任何地方引发 但是recover 只有在defer 调用的函数中有效
package main
import "fmt"
func fn1() {
fmt.Println("f1")
}
func fn2() {
panic("抛出一个异常")
}
func main() {
fn1()
fn2() //程序执行到这里抛出异常,然后程序退出,不在往下执行
fmt.Println("over...")
}
package main
import "fmt"
func fn1() {
fmt.Println("f1")
}
func fn2() {
defer func() {
err := recover()
if err != nil {
fmt.Println("扑捉异常,输出错误,程序继续执行")
}
}()
panic("抛出一个异常")
}
func main() {
fn1()
fn2() //程序执行到这里抛出异常,然后程序退出,不在往下执行
fmt.Println("over...")
}
/*
f1
扑捉异常,输出错误,程序继续执行
over...
*/
3 recover
recover 只有在defer 调用的函数中有效
package main
import "fmt"
func fn1(a,b int) int {
defer func() {
err := recover()
if err != nil {
fmt.Println("error: ",err)
}
}()
return a/b //除数为0,不符合语法报错,但是不影响程序继续执行
}
func main() {
fmt.Println(fn1(10,0))
fmt.Println("over")
}
/*
error: runtime error: integer divide by zero
0
over
*/
4 defer panic recover 结合使用
package main
import (
"errors"
"fmt"
)
// error 也是一个数据类型
func readFile(path string) error {
if path == "main.go" {
return nil
} else {
return errors.New("文件不存在")
}
}
func myFn() {
defer func() {
e := recover()
if e != nil {
fmt.Println("通知运维.文件不存在")
}
}()
funcErr := readFile("xxx.go")
if funcErr != nil {
panic(funcErr)
}
}
func main() {
myFn()
fmt.Println("继续执行。。。")
}
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!