GoLang之错误处理
2017-11-23 16:43
302 查看
错误处理
error
Go语言引入了一个错误处理的标准模式,即error接口,该接口定义如下:type error interface { Error() string }
对于大多数函数,如果要返回错误,可以将error作为多返回值的最后一个:
func foo(param int)(ret int, err error) { ... }
调用时的代码:
n, err := foo(0) if err != nil { // 错误处理 } else { // 使用返回值n }
我们还可以自定义错误类型,一个例子:
package main import "fmt" import "errors" //自定义的出错结构 type myError struct { arg int errMsg string } //实现Error接口 func (e *myError) Error() string { return fmt.Sprintf("%d - %s", e.arg, e.errMsg) } //两种出错 func error_test(arg int) (int, error) { if arg < 0 { return -1, errors.New("Bad Arguments - negtive!") }else if arg >256 { return -1, &myError{arg, "Bad Arguments - too large!"} } return arg*arg, nil } //相关的测试 func main() { for _, i := range []int{-1, 4, 1000} { if r, e := error_test(i); e != nil { fmt.Println("failed:", e) } else { fmt.Println("success:", r) } } }
defer
你可以在Go函数中添加多个defer语句,当函数执行到最后时,这些defer语句会按照逆序执行(即最后一个defer语句将最先执行),最后该函数返回。特别是当你在进行一些打开资源的操作时,遇到错误需要提前返回,在返回前你需要关闭相应的资源,不然很容易造成资源泄露等问题。如下代码所示,我们一般写打开一个资源是这样操作的:
func CopyFile(dst, src string) (w int64, err error) { srcFile, err := os.Open(src) if err != nil { return } defer srcFile.Close() dstFile, err := os.Create(dst) if err != nil { return } defer dstFile.Close() return io.Copy(dstFile, srcFile) }
如果defer后面一条语句干不完清理工作,也可以使用一个匿名函数:
defer func(){ ... }()
注意,defer语句是在return之后执行的,例如:
func test() (result int) { defer func() { result = 12 }() return 10 } func main() { fmt.Println(test()) // 12 }
panic() recover()
panic()函数用于抛出异常,recover()函数用于捕获异常,这两个函数的原型如下:func panic(interface{}) func recover() interface{}
当在一个函数中调用panic()时,正常的函数执行流程将立即终止,但函数中之前使用defer关键字延迟执行的语句将正常展开执行,之后该函数将返回到调用函数,并导致逐层向上执行panic()流程,直至所属的goroutine中所有正在执行的函数被终止。错误信息将被报告,包括在调用panic()函数时传入的参数,这个过程称为错误流程处理。
panic()接受一个interface{}参数,可支持任意类型,例如:
panic(404) panic("network broken") panic(Error("file not exists"))
在defer语句中,可以使用recover()终止错误处理流程,这样可以避免异常向上传递,但要注意recover()之后,程序不会再回到panic()那里,函数仍在defer之后返回。
func foo() { panic(errors.New("i'm a bug")) return } func test() (result int) { defer func() { if r := recover(); r != nil { err := r.(error) fmt.Println("Cache Exception:", err) } }() foo() return 10 } func main() { fmt.Println(test()) // 0 }
注意,在一个函数中panic被调用后,其defer语句仍会执行,
func foo()(n int) { defer func() { if r := recover(); r != nil { n++ // take effective } }() n++ // take effective panic(errors.New("i'm a bug")) n++ // take no effective return n }
相关文章推荐
- Golang错误和异常处理的正确姿势章
- Golang从入门到精通(二十):Golang错误处理之error
- [golang note] 错误处理
- Golang 错误和异常处理的正确姿势
- 【GoLang】GoLang 错误处理 -- 使用异常的思路进行处理
- 【GoLang】GoLang 错误处理 -- 官方推荐方式 示例
- 【GoLang】GoLang 错误处理 -- 异常处理思路示例
- Golang从入门到精通(二十一):Golang错误处理之panic-recover
- 【GoLang】GoLang 错误处理 -- 使用 error is value 的思路处理,检查并处理error
- golang 错误处理与异常
- Golang从入门到精通(二十二):Golang错误处理之defer
- golang错误处理之panic和recover
- golang的错误处理
- golang语法学习(二):控制语句,函数,以及错误处理。
- GOLANG错误处理最佳方案
- golang处理错误的艺术
- [golang note] 错误处理
- Golang巧用defer进行错误处理的方法
- golang语法学习(二):控制语句,函数,以及错误处理。
- 翻译golang的一篇文章-Go 语言的错误处理