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,yint)(int,error){ify==0{return0,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:13deadexitstatus1
如果有连续多次调用panic的场景,只有最后一次panic会被recover捕获处理,比如:
funcMyrecover(){iferr:=recover();err!=nil{log.Fatalln(err)}}funcmain(){deferMyrecover()deferfunc(){panic("abadproblem")}()panic("aproblem")}输出:2017/02/0911:31:50abadproblemexitstatus1
recover只有在延迟调用函数中才能得到正常工作,比如:
funcmain(){deferMyrecover()deferlog.Println(recover())deferprintln(recover())panic("aproblem")}输出:(0x0,0x0)2016/11/1207:07:54<nil>2016/11/1207:07:54aproblemexitstatus1
在日常开发过程中,经常需要进行调试,可以使用函数输出完整的调用栈信息,比如:
funcMyrecover(){iferr:=recover();err!=nil{fmt.Println(err)debug.PrintStack()//log.Fatalln(err)}}funcmain(){deferMyrecover()panic("aproblem")}输出:aproblemgoroutine1[running]:runtime/debug.Stack(0xc42002c010,0xc42003fe20,0x1)/root/data/go/src/runtime/debug/stack.go:24+0x79runtime/debug.PrintStack()/root/data/go/src/runtime/debug/stack.go:16+0x22main.Myrecover()/root/data/gopath/test/panic.go:10+0x85panic(0x48a5e0,0xc42000a320)/root/data/go/src/runtime/panic.go:458+0x243main.main()/root/data/gopath/test/panic.go:16+0x8d
日常开发中,只有在系统发生了不可恢复性或无法正常工作的错误可以使用panic,比如端口号被占用、数据库未启动、文件系统错误等,否则不建议使用。
声明:本站所有文章资源内容,如无特殊说明或标注,均为采集网络资源。如若本站内容侵犯了原著者的合法权益,可联系本站删除。