错误处理

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之错误处理的更多相关文章

  1. 个人犯的一个golang routine错误

    这个其实不是错误,2个写法没有区别.-2015.11.22 认识golang也不少时间了,也做过几个项目.最近发现之前用golang写的一个服务,内存涨得比较快,一直没找出来原因来.今天把疑惑发到群里 ...

  2. [golang note] 错误处理

    错误处理 • 错误处理的标准模式 √ golang错误处理的标准模式:error接口. √ golang函数如果要返回错误,规范上是将error作为多返回值中的最后一个,但这并非是强制要求. ▶ er ...

  3. [Golang]-4 错误处理、Panic、Defer

    目录 错误和异常 案例 Panic Defer 使用 defer+recover 来处理错误 参考文章: Go 语言使用一个独立的·明确的返回值来传递错误信息的.这与使用异常的 Java 和 Ruby ...

  4. golang处理错误的艺术

    golang中关键API的调用都会在最后返回err(golang多值返回). 调用者可以选择处理, 或者不处理该err, 或原装返回给上一层的调用者. golang中的err是error类型, typ ...

  5. Go_19: Golang 中错误与异常需要重新认识

    如何进行错误处理,这是一个Go程序员之间,特别是一些新的Go程序员,会经常讨论的问题.讨论到最后往往由于以下代码的多次出现而变成了抱怨. if err != nil { return err } 我们 ...

  6. Golang 中错误与异常需要重新认识

    如何进行错误处理,这是一个Go程序员之间,特别是一些新的Go程序员,会经常讨论的问题.讨论到最后往往由于以下代码的多次出现而变成了抱怨. if err != nil { return err } 我们 ...

  7. golang error错误处理

    error定义 数据结构 go语言error是一普通的值,实现方式为简单一个接口. // The error built-in interface type is the conventional i ...

  8. 『GoLang』错误处理

    Go 没有像 Java 和 .NET 那样的 try/catch 异常机制:不能执行抛异常操作.但是有一套 defer-panic-and-recover 机制. Go 的设计者觉得 try/catc ...

  9. golang常见错误

    import import unuse package: error : imported and not used: "os" := = c := 1 // error non- ...

随机推荐

  1. BZOJ2368 : Modern Art Plagiarism 树同构

    枚举$T_1$的树根,然后DP,设$f[i][j]$表示$T_1$的子树$i$是否存在包括i的连通子树与$T_2$的子树$j$同构. 若$j$是叶子,那么显然可以. 若$deg_i<deg_j$ ...

  2. X-factor Chains [POJ3421] [素数]

    Description    给定一个正整数X, 一个长度为m的X-因子链是由m+1个整数组成的.其中    1 = X0, X1, X2, …, Xm = X 满足Xi < Xi+1 且 Xi ...

  3. mysql找安装路经,更改密码

    1:如果安装了mysql但是启动不了,可以到C:/Windows/System32的cmd.exe,用管理员身份打开,然后输入net strat mysql即可 2:忘记安装路经       sele ...

  4. multiprocess模块

    什么是进程 什么是进程 进程是计算机中的程序关于某数据集合一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础,进程与进程之间数据隔离,执行过程异步 为什么会出现进程的概念 合理利用 ...

  5. yii2过滤器(filter)

    一.VerbFilter VerbFilter检查请求动作的HTTP请求方式是否允许执行, 如果不允许,会抛出HTTP 异常 use yii\filters\VerbFilter; public fu ...

  6. yii2 用 bootstrap 给元素添加背景色

    使用 bootstrap 给元素添加背景色 1.bootstrap 官网:http://getbootstrap.com/ 2.bootstrap 中文官网:http://v3.bootcss.com ...

  7. Android Studio 创建不同分辨率的图标

    参考资料 Android Studio怎么创建不同分辨率的图标  

  8. python常用库之random

    random是内建(built-in)函数,作用是产生随机数,使用较多. 1.导入模块 首先是导入模块: import random 接着就可以调用random模块下的函数了,例如: random.r ...

  9. vue-cli webpack2项目打包优化

    减小文件搜索范围 配置 resolve.modules Webpack的resolve.modules配置模块库(即 node_modules)所在的位置,在 js 里出现 import 'vue' ...

  10. 杭电acm2059-龟兔赛跑 java

    一看题就知道是动态规划,不过这要看下如何设置变化数组了 先分析这道题:兔子到达终点的时间时固定的,因此只需要考虑乌龟了,乌龟骑电车和骑自行车的时间,然后计算,因为中间有N个充电站,可以看做N个点(到起 ...