go中的panic defer recover

panic

panic是个函数,有一个空接口类型的入参(可传任意类型,如字符串、error等等)

func main() {
    fmt.Println(10)
    panic("这是一个恐慌")
    fmt.Println(20)
}

只会打印10,不会打印20,main函数非零退出

defer是个关键字,后面跟一个函数

func ReturnTest() string {
	fmt.Println("我是return执行的")
	return "return"
}

func DeferTest() string {
	defer fmt.Println("我是defer执行的")
	return ReturnTest()
}

func main(){
	defer DeferTest()

	fmt.Println("我是main")
}

执行结果为:
我是main
我是return执行的
我是defer执行的
由此可以看出,defer是最后执行的,比return还要靠后

recover

recover也是个函数,没有入参,出参是个空接口类型,具体返回什么类型取决于使用的场景:

如果recover()在defer后面的函数中调用,则如果goroutine panic了,则recover()函数返回panic函数的入参,同时panic会被压制住,相当于异常被catch住,程序不会非零退出了,否则返回nil。

如果recover()不是在defer后面的函数中调用,则返回nil,且不会压制panic。

package main

import (
	"errors"
	"fmt"
	"reflect"
	// "time"
)

func MayPanic(i int) int {
    if i == 0 {
        panic("不能为0")
    } else if i < 0 {
        panic(errors.New("不能小于0"))
    }
    return 1
}

func main() {
    defer func() {
        if r := recover(); r != nil {
			fmt.Println("========================")
            fmt.Println(r)
            fmt.Println(reflect.TypeOf(r))
        }
    }()
	fmt.Println("我应该先执行才对呀。。。。")
    // i := MayPanic(0)
    // i := MayPanic(-1)
	i := MayPanic(10)
    fmt.Println(i)
}

如果不理解可以把代码拷贝下来,然后把MayPanic依次打开看看输出结果就知道了

经典使用

package main

import (
	"fmt"
	"time"
)

func proc(){
	panic("ok")
}
func main() {
	
	go func() {
		// 1 在这里需要你写算法
		// 2 要求每秒调用一次proc函数
		// 3 要求程序不能退出
	}()
	select{
	}
}
package main

import (
	"fmt"
	"time"
)

func proc(){
	panic("ok")
}
func main() {
	
	go func() {
		// 1 在这里需要你写算法
		// 2 要求每秒调用一次proc函数
		// 3 要求程序不能退出

		t := time.NewTicker(time.Second)
		for{
			select {
				case <-t.C:
					go func(){
						defer func(){
							if err := recover(); err != nil {
								fmt.Println(err)
							}
						}()
						proc()
					}()
			}
		}
	}()

	select{
	}
}

try catch finally封装

package main

import (
    "log"
)

type ExceptionStruct struct {
    Try     func()
    Catch   func(Exception)
    Finally func()
}
type Exception interface{}

func Throw(up Exception) {
    panic(up)
}
func (ex ExceptionStruct) Do() {
    if ex.Finally != nil {
        defer ex.Finally()
    }
    if ex.Catch != nil {
        defer func() {
            if e := recover(); e != nil {
                ex.Catch(e)
            }
        }()
    }
    ex.Try()
}

func main() {
    log.Println("开始执行...")
    ExceptionStruct{
        Try: func() {
            log.Println("try...")
            Throw("发生了错误")
        },
        Catch: func(e Exception) {
            log.Println("exception=", e)
        },
        Finally: func() {
            log.Println("Finally...")
        },
    }.Do()
    log.Println("结束运行")
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值