golang 函数四 (错误处理)
为了方便实现自定义错误类型,Go语言标准库中将error定义为接口类型。比如: typeerrorinterface{ Error()string } 按照Go语言编程习惯,error总是最后一个函数返回值,并且标准库提供了创建函数,可以方便的创建错误消息的error对象。比如: funcdivTest(x,yint)(int,error){ ify==0{ return0,errors.New("divisionbyzero")//创建错误消息的error对象 } returnx/y,nil } funcmain(){ v,err:=divTest(3,0) iferr!=nil{ log.Fatalln(err.Error()) } println(v) } 日常开发中,我们需要根据需求自定义错误类型,可以存放更多的上下文信息,或者根据错误类型做出相应的错误处理。比如: typeNegativeErrorstruct{ x,yint } func(NegativeError)Error()string{ return"negativevalueerror" } typeMolErrorstruct{ x,yint } func(MolError)Error()string{ return"devisionbyzero" } funcmolTest(x,MolError{x,y} } ifx<0||y<0{ return0,NegativeError{x,y} } returnx%y,nil } funcmain(){ v,err:=molTest(3,-1) iferr!=nil{ switche:=err.(type){//获取错误类型 caseMolError: println(e.x,e.y) caseNegativeError: println(e.x,e.y) default: println(e) } log.Fatalln(err.Error()) } println(v) } 与error相比,panic/recover 在应用上更类似于 try/catch 结构化。比如: funcpanic()interface{} funcrecover()interface{} 两者区别:panic 立即中断当前函数处理流程,执行延迟调用。recover在延迟调用中可以捕获并返回panic产生的错误对象,比如: funcMyrecover(){ iferr:=recover();err!=nil{ log.Fatalln(err) } } funcmain(){ println("start...") deferMyrecover() panic("dead") println("end...") } 输出: start... 2017/02/0911:24:13dead exitstatus1 如果有连续多次调用panic的场景,只有最后一次panic会被recover捕获处理,比如: funcMyrecover(){ iferr:=recover();err!=nil{ log.Fatalln(err) } } funcmain(){ deferMyrecover() deferfunc(){ panic("abadproblem") }() panic("aproblem") } 输出: 2017/02/0911:31:50abadproblem exitstatus1 recover只有在延迟调用函数中才能得到正常工作,比如: funcmain(){ deferMyrecover() deferlog.Println(recover()) deferprintln(recover()) panic("aproblem") } 输出: (0x0,0x0) 2016/11/1207:07:54<nil> 2016/11/1207:07:54aproblem exitstatus1 在日常开发过程中,经常需要进行调试,可以使用函数输出完整的调用栈信息,比如: funcMyrecover(){ iferr:=recover();err!=nil{ fmt.Println(err) debug.PrintStack() //log.Fatalln(err) } } funcmain(){ deferMyrecover() panic("aproblem") } 输出: aproblem goroutine1[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,比如端口号被占用、数据库未启动、文件系统错误等,否则不建议使用。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |