[Golang]-4 错误处理、Panic、Defer
Go 语言使用一个独立的·明确的返回值来传递错误信息的。这与使用异常的 Java 和 Ruby 以及在 C 语言中经常见到的超重的单返回值/错误值相比,
Go 语言的处理方式能清楚的知道哪个函数返回了错误,并能像调用那些没有出错的函数一样调用。
错误和异常
错误:指的是可能出现问题的地方出现了问题;
比如打开一个文件时失败,这种情况在人们的意料之中 ;异常:指的是不应该出现问题的地方出现了问题;
比如引用了空指针,这种情况在人们的意料之外。可见,错误是业务过程的一部分,而异常不是 。
Golang中引入error接口类型作为错误处理的标准模式,如果函数要返回错误,则返回值类型列表中肯定包含error。
error处理过程类似于C语言中的错误码,可逐层返回,直到被处理。
案例
package main
import (
"errors"
"fmt"
)
// 按照惯例,错误通常是最后一个返回值并且是 error 类型,一个内建的接口。
func f1(arg int) (int, error) {
if arg == 42 {
// errors.New 构造一个使用给定的错误信息的基本error 值。
return -1, errors.New("can't work with 42")
}
// 返回错误值为 nil 代表没有错误。
return arg + 3, nil
}
// 通过实现 Error 方法来自定义 error 类型是可以的。这里使用自定义错误类型来表示上面的参数错误。
type argError struct {
arg int
prob string
}
func (e *argError) Error() string {
return fmt.Sprintf("%d - %s", e.arg, e.prob)
}
func f2(arg int) (int, error) {
if arg == 42 {
// 使用 &argError 语法来建立一个新的结构体,并提供了 arg 和 prob 这个两个字段的值。
return -1, &argError{arg, "can't work with it"}
}
return arg + 3, nil
}
func main() {
// 下面的两个循环测试了各个返回错误的函数。注意在 if行内的错误检查代码,在 Go 中是一个普遍的用法。
// range 提供每项的索引和值。我们不需要索引,所以们使用空值定义符_来忽略它。有时候是需要这个索引的。
for _, i := range []int{7, 42} {
if r, e := f1(i); e != nil {
fmt.Println("f1 failed:", e)
} else {
fmt.Println("f1 worked:", r)
}
}
for _, i := range []int{7, 42} {
if r, e := f2(i); e != nil {
fmt.Println("f2 failed:", e)
} else {
fmt.Println("f2 worked:", r)
}
}
// 你如果想在程序中使用一个自定义错误类型中的数据,你需要通过类型断言来得到这个错误类型的实例。
_, e := f2(42)
if ae, ok := e.(*argError); ok {
fmt.Println(ae.arg)
fmt.Println(ae.prob)
}
}
输出结果:
f1 worked: 10
f1 failed: can't work with 42
f2 worked: 10
f2 failed: 42 - can't work with it
42
can't work with it
Golang中引入两个内置函数panic (['pænɪk]恐惧)和recover ([.ri'kʌvər]恢复)来触发和终止异常处理流程,同时引入关键字defer([dɪ'fɜr])来延迟执行defer后面的函数。
Panic
panic 意味着有些出乎意料的错误发生。通常我们用它来表示程序正常运行中不应该出现的,或者我们没有处理好的错误。
import "os"
func main() {
// 我们将使用 panic 来检查预期外的错误。这个是为 panic 准备的例子。
panic("a problem")
// panic 的一个基本用法就是在一个函数返回了错误值但是我们并不知道(或者不想)处理时终止运行。
// 这里是一个在创建一个新文件时返回异常错误时的panic 用法。
_, err := os.Create("/tmp/file")
if err != nil {
panic(err)
}
}
输出:
panic: a problem
goroutine 1 [running]:
main.main()
/.../panic.go:10 +0x45
Defer
Defer 被用来确保一个函数调用在程序执行结束前执行。同样用来执行一些清理工作。 defer 用在像其他语言中的 ensure 和 finally用到的地方。
假设我们想要创建一个文件,向它进行写操作,然后在结束时关闭它。这里展示了如何通过 defer 来做到这一切。
import (
"fmt"
"os"
)
func main() {
// 在 closeFile 后得到一个文件对象,我们使用 defer通过 closeFile 来关闭这个文件。
// 这会在封闭函数(main)结束时执行,就是 writeFile 结束后。
f := createFile("defer.txt")
defer closeFile(f)
writeFile(f)
}
func createFile(p string) *os.File {
fmt.Println("creating")
f, err := os.Create(p)
if err != nil {
panic(err)
}
return f
}
func writeFile(f *os.File) {
fmt.Println("writing")
fmt.Fprintln(f, "data")
}
func closeFile(f *os.File) {
fmt.Println("closing")
f.Close()
}
输出:
creating
writing
closing
明显,这个文件在写入后是已关闭的。
使用 defer+recover 来处理错误
import (
"fmt"
)
func main() {
// 使用defer + recover来捕获和处理异常
defer func() {
// recover 是内置函数,可以捕获异常
err := recover()
if err != nil {
fmt.Println("err=", err)
}
}()
num1 := 10
num2 := 0
res := num1 / num2
fmt.Println("res=", res)
}
输出:
err= runtime error: integer divide by zero
参考文章:
- Golang错误和异常处理的正确姿势:https://www.cnblogs.com/zhangboyu/p/7911190.html
[Golang]-4 错误处理、Panic、Defer的更多相关文章
- Golang错误处理函数defer、panic、recover、errors.New介绍
在默认情况下,当发生错误(panic)后,程序就会终止运行 如果发生错误后,可以捕获错误,并通知管理人员(邮件或者短信),程序还可以继续运行,这当然无可厚非 errors.New("错误信息 ...
- 【GoLang】panic defer recover 深入理解
唉,只能说C程序员可以接受go的错误设计,相比java来说这个设计真的很差劲! 我认为知乎上说的比较中肯的: 1. The key lesson, however, is that errors ar ...
- 『GoLang』错误处理
Go 没有像 Java 和 .NET 那样的 try/catch 异常机制:不能执行抛异常操作.但是有一套 defer-panic-and-recover 机制. Go 的设计者觉得 try/catc ...
- [golang note] 错误处理
错误处理 • 错误处理的标准模式 √ golang错误处理的标准模式:error接口. √ golang函数如果要返回错误,规范上是将error作为多返回值中的最后一个,但这并非是强制要求. ▶ er ...
- GoLang之错误处理
错误处理 error Go语言引入了一个错误处理的标准模式,即error接口,该接口定义如下: type error interface { Error() string } 对于大多数函数,如果要返 ...
- 个人犯的一个golang routine错误
这个其实不是错误,2个写法没有区别.-2015.11.22 认识golang也不少时间了,也做过几个项目.最近发现之前用golang写的一个服务,内存涨得比较快,一直没找出来原因来.今天把疑惑发到群里 ...
- golang error错误处理
error定义 数据结构 go语言error是一普通的值,实现方式为简单一个接口. // The error built-in interface type is the conventional i ...
- 解决Ubuntu启动错误——kernel panic not syncing vfs unable to mount root fs on unknown-block 0 0 – error
最近在倒腾Ubuntu,然后想着怎么美化一下界面,于是照着网上的教程整了一下Flatabulous这个软件,然后好像/boot就满了.关机之后再开机就出现了如题所述的错误,无法开机,也无法进入reco ...
- golang处理错误的艺术
golang中关键API的调用都会在最后返回err(golang多值返回). 调用者可以选择处理, 或者不处理该err, 或原装返回给上一层的调用者. golang中的err是error类型, typ ...
随机推荐
- 【Docker】安装docker18.09.6后,无法启动
------------------------------------------------------------------------------------------------- | ...
- 【RAC】10grac添加节点,详细步骤
RAC物理结构 现在的RAC环境是二个节点: dbp,dbs, 这个实验就是添加节点dbi. dbp,dbs和dbi节点的信息规划如下: 服务器主机名 dbp dbs dbi 公共IP地址(eth0) ...
- Centos6.9安装ACFS
安装完oracle 11GR2的RAC后,使用asmca打开图形化界面后,发现Volumes和ASM Cluster File System两个选项卡不能用 原因是因为ACFS不支持CentOS 解决 ...
- 核酸检测:让我明白AQS原理
春节越来越近了,疫情也越来越严重,但挡不住叫练携一家老小回老家(湖北)团聚的冲动.响应国家要求去我们做核酸检测了. 独占锁 早上叫练带着一家三口来到了南京市第一医院做核酸检测,护士小姐姐站在医院门口拦 ...
- Vue的核心思想
Vue的核心思想主要分为两部分: 1.数据驱动 2.组件系统 1.数据驱动 在传统的前端交互中,我们是通过Ajax向服务器请求数据,然后手动的去操作DOM元素,进行数据的渲染,每当前端数据交互变化时 ...
- Java中的Date类型无法赋值给数据库的datetime类型
因为Java中new Date()的结果是"Thu Aug 27 19:03:54 CST 2020",而mysql中的datetime不接受这样的日期格式,插入数据会报错. 解决 ...
- Python爬虫:数据分析小能手:JSON库的用法
JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式,易于人阅读和编写. 给大家推荐一个Python交流的q裙,大家在学习遇到了什么问题都可以进群一起交流,大家 ...
- 流量染色与gRPC服务托管 微服务协作开发、灰度发布之流量染色 灰度发布与流量染色
大规模微服务场景下灰度发布与流量染色实践 https://mp.weixin.qq.com/s/UBoRKt3l91ffPagtjExmYw [go-micro]微服务协作开发.灰度发布之流量染色 - ...
- 深入理解SPI机制-服务发现机制
https://www.jianshu.com/p/3a3edbcd8f24 SPI ,全称为 Service Provider Interface,是一种服务发现机制.它通过在ClassPath路径 ...
- 自修改代码 on the fly 动态编译 即时编译 字节码
https://zh.wikipedia.org/wiki/自修改代码 自修改代码(Self-modifying code)是指程序在运行期间(Run time)修改自身指令.可能的用途有:病毒利用此 ...