golang 函数四 (错误处理)
admin
2023-08-01 09:04:25
0

为了方便实现自定义错误类型,Go语言标准库中将error定义为接口类型。比如:

type error interface{
    Error() string
}

按照Go语言编程习惯,error总是最后一个函数返回值,并且标准库提供了创建函数,可以方便的创建错误消息的error对象。比如:

func divTest(x ,y int)(int, error){
    if y == 0{
        return 0, errors.New("division by zero") //创建错误消息的error对象
    }   
    return x/y,nil
}
func main(){
    v, err := divTest(3,0)
    if err != nil{
        log.Fatalln(err.Error())
    }   
    println(v)
}

日常开发中,我们需要根据需求自定义错误类型,可以存放更多的上下文信息,或者根据错误类型做出相应的错误处理。比如:

type NegativeError struct{
    x, y int
}
func (NegativeError)Error()string{
    return "negative value error"
}

type MolError struct {
    x, y int
}
func (MolError)Error()string{
    return "devision by zero"
}

func molTest(x ,y int)(int, error){
    if y == 0{
        return 0, MolError{x,y}
    }
    if x < 0 || y < 0{
        return 0, NegativeError{x,y}
    }
    return x%y,nil
}

func main(){
    v, err := molTest(3,-1)
    if err != nil{
        switch e := err.(type){     //获取错误类型
            case MolError:
                println(e.x,e.y)
            case NegativeError:
                println(e.x,e.y)
            default:
                println(e)
        }
        log.Fatalln(err.Error())
    }
    println(v)
}

与error相比,panic/recover 在应用上更类似于 try/catch 结构化。比如:

func panic() interface{}   
func recover() interface{}

两者区别:panic 立即中断当前函数处理流程,执行延迟调用。recover在延迟调用中可以捕获并返回panic产生的错误对象,比如:

func Myrecover(){
    if err := recover(); err != nil{
        log.Fatalln(err)
    }   
}

func main(){
    println("start...")
    defer Myrecover()
    panic("dead")
    println("end...")
}
输出:
start...
2017/02/09 11:24:13 dead
exit status 1

如果有连续多次调用panic的场景,只有最后一次panic会被recover捕获处理,比如:

func Myrecover(){
    if err := recover(); err != nil{
        log.Fatalln(err)
    }   
}

func main(){
    defer Myrecover()
    defer func(){
        panic("a bad problem")
    }()
    panic("a problem")
}
输出:
2017/02/09 11:31:50 a bad problem
exit status 1

recover只有在延迟调用函数中才能得到正常工作,比如:

func main() {
    defer Myrecover()
    defer log.Println(recover())
    defer println(recover())
    panic("a problem") 
}
输出:
(0x0,0x0)
2016/11/12 07:07:54 
2016/11/12 07:07:54 a problem
exit status 1

在日常开发过程中,经常需要进行调试,可以使用函数输出完整的调用栈信息,比如:

func Myrecover(){
    if err := recover(); err != nil{
        fmt.Println(err)
        debug.PrintStack()
        //log.Fatalln(err)
    }
}
func main(){
    defer Myrecover()
    panic("a problem")
}
输出:
a problem
goroutine 1 [running]:
runtime/debug.Stack(0xc42002c010, 0xc42003fe20, 0x1)
	/root/data/go/src/runtime/debug/stack.go:24 +0x79
runtime/debug.PrintStack()
	/root/data/go/src/runtime/debug/stack.go:16 +0x22
main.Myrecover()
	/root/data/gopath/test/panic.go:10 +0x85
panic(0x48a5e0, 0xc42000a320)
	/root/data/go/src/runtime/panic.go:458 +0x243
main.main()
	/root/data/gopath/test/panic.go:16 +0x8d

日常开发中,只有在系统发生了不可恢复性或无法正常工作的错误可以使用panic,比如端口号被占用、数据库未启动、文件系统错误等,否则不建议使用。

相关内容

热门资讯

姚顺雨之后,又一名前OpenA... 去年姚顺雨加入腾讯后,又一名OpenAI前研究员加入腾讯。 据腾讯相关负责人介绍,OpenAI 前研...
原快手高级副总裁、研发线负责人... 北京时间7月8日,据知情人士透露,原快手高级副总裁、研发线负责人陈彬已加入小红书,担任技术副总裁。有...
先进材料登上国新办发布会 研发... 每经记者:张宏 每经编辑:董兴生 7月8日下午,国新办举行“新征程上的奋斗者”中外记者见面会。来自人...
内存一年暴涨300%!5000... 快科技7月8日消息,2026年数码市场迎来罕见涨价风暴,核心存储配件价格疯狂冲高,主流16G DDR...
数智重塑视听产业 海看鲸灵AI... 2026年7月6日至8日,以“新视听·新文艺·新征程”为主题的2026山东网络视听大会在烟台市蓬莱区...
原创 现... 2026年的国内旗舰手机市场里,华为Mate80系列已经交出了一份相当亮眼的成绩单:上市七个多月累计...
原创 马... 前几天,卡纳维拉尔角天军基地又飞起一枚猎鹰九号火箭。这次任务看着很不起眼——不发星链,不送卫星,直播...
新京报社社长毛晓刚:搭建跨领域... “站在‘十五五’规划开局起步的历史节点,中国经济正在完成从传统要素驱动向创新驱动的关键切换,‘新质启...
“大连一号”无人机海上首飞 原标题:大连理工大学自主研发 “大连一号”成功首飞 跨海续航超1300公里 可在6级风中垂直起降 ...
出差通勤新利器:OPPO Fi... 在快节奏的现代生活中,手机早已成为我们工作与旅途中不可或缺的伙伴。无论是频繁出差、日常通勤,还是周末...