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]-4 错误处理、Panic、Defer的更多相关文章

  1. Golang错误处理函数defer、panic、recover、errors.New介绍

    在默认情况下,当发生错误(panic)后,程序就会终止运行 如果发生错误后,可以捕获错误,并通知管理人员(邮件或者短信),程序还可以继续运行,这当然无可厚非 errors.New("错误信息 ...

  2. 【GoLang】panic defer recover 深入理解

    唉,只能说C程序员可以接受go的错误设计,相比java来说这个设计真的很差劲! 我认为知乎上说的比较中肯的: 1. The key lesson, however, is that errors ar ...

  3. 『GoLang』错误处理

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

  4. [golang note] 错误处理

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

  5. GoLang之错误处理

    错误处理 error Go语言引入了一个错误处理的标准模式,即error接口,该接口定义如下: type error interface { Error() string } 对于大多数函数,如果要返 ...

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

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

  7. golang error错误处理

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

  8. 解决Ubuntu启动错误——kernel panic not syncing vfs unable to mount root fs on unknown-block 0 0 – error

    最近在倒腾Ubuntu,然后想着怎么美化一下界面,于是照着网上的教程整了一下Flatabulous这个软件,然后好像/boot就满了.关机之后再开机就出现了如题所述的错误,无法开机,也无法进入reco ...

  9. golang处理错误的艺术

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

随机推荐

  1. 【Oracle】常见等待事件处理

    1.查看数据库中需要关注的等待事件: select sw.seq#,sw.sid||','||s.serial# sids,s.username,sw.event,sw.P1,sw.p2,sw.p3, ...

  2. 【VNC】vnc安装oracle的时候不显示图形化界面

    背景: 在虚拟机搭建了一个环境,准备安装oracle.但是环境都配置完成后,执行./runInstaller的时候,没有界面显示,只显示下面的界面 多次尝试后,发现,还是这样,期初是因为没有配置DIS ...

  3. 如何用Python中自带的Pandas和NumPy库进行数据清洗

    一.概况 1.数据清洗到底是在清洗些什么? 通常来说,你所获取到的原始数据不能直接用来分析,因为它们会有各种各样的问题,如包含无效信息,列名不规范.格式不一致,存在重复值,缺失值,异常值等..... ...

  4. 使用Spring的RestTemplate进行接口调用

    引自:http://www.zimug.com/ 1.常见的http服务的通信方式 经常使用的方式有HttpClient.OkHttp.RestTemplate.其中RestTemplate是一种更优 ...

  5. Databricks 第10篇:Job

    Job是立即运行或按计划运行notebook或JAR的一种方法,运行notebook的另一种方法是在Notebook UI中以交互方式运行. 一,使用UI来创建Job 点击"Jobs&quo ...

  6. eNSP启动设备AR1失败记一次解决步骤

    eNSP稳定版本下载:   微信搜索公众号"疯刘小三" 关注后回复ensp即可获得下载链接地址 eNSP V100R002C00B510 Setup.exe 最近在用eNSp的时候 ...

  7. 🙈 如何隐藏你的热更新 bundle 文件?

    如果你喜欢我写的文章,可以把我的公众号设为星标 ,这样每次有更新就可以及时推送给你啦. 前段时间我们公司的一个大佬从一些渠道得知了一些小道消息,某国民级 APP 因为 Apple App Store ...

  8. C++ 无法打开 源 文件 "ntddk.h"

    原因是SDK版本太高了,或者版本不对应WDK,换一个SDK版本就好了.

  9. gRPC Motivation and Design Principles | gRPC https://grpc.io/blog/principles/

    gRPC Motivation and Design Principles | gRPC https://grpc.io/blog/principles/

  10. Hash Join: Basic Steps

    Joins https://docs.oracle.com/database/121/TGSQL/tgsql_join.htm#TGSQL242 tidb/index_lookup_hash_join ...