defer
Golang中的defer会将其后面跟随的语句进行延迟处理。在defer归属的函数即将返回时,将延迟处理的语句按defer定义的逆序执行。也就是说,最先被defer的语句最后被执行。
fmt.Println("开始")
defer fmt.Println(1)
defer fmt.Println(2)
defer fmt.Println(3)
fmt.Println("结束")
//开始
//结束
//3
//2
//1
defer在函数中必须是匿名自执行函数
func f1(){
fmt.Println("开始")
defer func(){
fmt.Println("aaa")
fmt.Println("bbb")
}()
fmt.Println("结束")
}
//开始
//结束
//aaa
//bbb
- 对比f1和f2的返回值
匿名返回值
func f1(){
var a int
defer func(){
a++
}()
return a
}
func main(){
fmt.Println(f1())//0
}
命名返回值
func f2()(a int){
defer func(){
a++
}
return a
}
func main(){
fmt.Println(f2())//1
}
- 返回值赋值
- 运行defer
- 执行return指令
- demo
func f3()(x int){
defer func(x int) {
x++
}(x)
return 5
}
func main(){
fmt.Println(f3())//5
}
defer注册要延迟执行的函数时,该函数所有的参数都需要确定其值
func calc (index string, a, b int) int {
ret := a + b
fmt.Println(index, a, b, ret)
return ret
}
func main() {
x := 1
y := 2
defer calc("AA", x, calc("A", x, y))
x = 10
defer calc("BB", x, calc("B", x, y))
y = 20
}
注册顺序
defer calc("AA", x, calc("A", x, y))//A 1 2 3
defer calc("BB", x, calc("B", x, y))//B 10 2 12
执行顺序
defer calc("BB", x, calc("B", x, y))//BB 10 12 22
defer calc("AA", x, calc("A", x, y))//AA 1 3 4
panic/recover
Golang中目前没有异常机制,可以使用panic/recover模式来处理错误。
panic可以在任何地方引发,但recover只有在defer调用的函数中有效。
func fn1(){
fmt.Println("fn1")
}
func fn2(){
panic("抛出一个异常")
}
func main(){
fn1()
fn2()
fmt.Println("结束")
}
//fn1
//抛出一个异常
可以看到,panic后面的程序终止执行了
- recover和defer
func fn1(){
fmt.Println("fn1")
}
func fn2(){
defer func(){
err := recover() //如果没有异常,err默认为nil
if err != nil {
fmt.Println("err:",err)
}
}()
panic("抛出一个异常")
}
func main(){
fn1()
fn2()
fmt.Println("结束")
}
// fn1
// err: 抛出一个异常
// 结束
- demo1
func fn1(a int, b int) {
defer func(){
err := recover()
if err != nil {
fmt.Println("error",err)
}
}()
fmt.Println( a / b )
}
func main(){
fn1(10, 0)
fmt.Println("结束")
}
//error runtime error: integer divide by zero
//结束
- demo2
//模拟读取文件的方法
func readFile(fileName string) error {
if fileName === "main.go" {
return nil
} else {
return errors.New("读取文件失败")
}
}
func myFn(){
defer func(){
err := recover()
if err != nil {
fmt.Println("给管理员发送邮件")
}
}()
err := readFile("xxx.go")
if err != nil {
panic(err)
}
}
func main() {
myFn()
fmt.Println("继续执行...")
}
//给管理员发送邮件
//继续执行...
有疑问加站长微信联系(非本文作者)