一门优秀的语言少不了优秀的错误或异常处理机制,golang也不例外,它有非常简洁的和实用的错误处理机制
前言
平时在项目开发过程中少不了对错误的处理,一个好用的系统首先要确保其健壮性,不能经常发生错误就卡死之类的情况。为了让我们的程序更加健壮,我们就需要知道golang里的错误处理机制是怎么样的,这篇文章带大家一起学习。
做过JAVA项目的猿们都知道,在JAVA中经常使用的try{…}catch{…}finally{…}就是用来干这个事情的。
一、什么是错误
初学者一般都会有下面这些问题:
- 程序为什么会有错误?
- 为什么要进行处理?
让我们一起来看一下下面这段代码:
func test() {
num1 := 20
num2 := 0
num3 := num1 / num2
fmt.Printf("num3的类型是:%T, 值为:%v\n", num3, num3)
}
func main() {
test()
fmt.Println("下面的代码!!!!")
fmt.Println("~~~~下面的代码!!!!")
}
这段代码在编辑器里并不会报错,它只有在运行时才会报错,而且一旦报错程序就终止了,这在实际项目中是致命的问题。
我们来看一下它的输出结果:
panic: runtime error: integer divide by zero
goroutine 1 [running]:
main.main()
C:/workplace/go/src/selftPro/TextStr.go:11 +0x11
Process finished with the exit code 2
从运行结果上可以看到直接报错并退出了,后面的代码也没有执行
代码中num2我们这里是直接写死了,在真实的项目中,这里的数据都可能来自数据库(或是用户输入),我们写程序的时候是不知道会有哪些值,所以我们需要把能想到的错误情况都提前在程序里处理了,避免程序直接退出或是卡死。
- 在默认情况下,当发生错误后(panic),程序就是退出(崩溃或卡死)
- 如果我们希望,当发生错误时,可以捕获到错误,并进行相应的处理,保证程序可以继续执行。
- 我们就需要学会使用golang的错误机制
二、基本说明
- golang追求简洁优雅,所以,golang中不支持传统的try{…}catch{…}finally{…}
- golang引入的处理方式为:defer, panic, recover
- 使用流程可以简单描述为:go 程序中发生错误抛出一个panic的异常,然后在defer中通过recover捕获这个异常,然后正常处理。
三、错误捕获方法
使用时需要在你认为会发生错误的函数里定义一个defer的逆名函数,在逆名函数中用recover捕获错误信息
前言里的示例更改如下:
func test() {
defer func() {
err := recover()
if nil != err {
fmt.Println("捕获到错误信息:", err)
fmt.Println("这里可以对错误进行处理......")
}
}()
num1 := 20
num2 := 0
num3 := num1 / num2
fmt.Printf("num3的类型是:%T, 值为:%v\n", num3, num3)
}
func main() {
test()
fmt.Println("下面的代码!!!!")
fmt.Println("~~~~下面的代码!!!!")
}
运行结果:
捕获到错误信息: runtime error: integer divide by zero
这里可以对错误进行处理......
下面的代码!!!!
~~~~下面的代码!!!!
四、自定义错误
golang 也支持自定义错误,使用errors.New() 和 panic内置函数
- errors.new(“错误说明”) ,这个函数会返回一个error类型的值,表示一个错误
- panic 内置函数,接收一个interface{}类型的值(也就是任何值都可以)作为参数,可以接收error类型的变量,输出错误信息,并退出程序。
引入包: import errors
示例代码如下(未发生错误时):
// OpenDb 超级用户打开数据库方法
func OpenDb(userName string) (err error) {
if "admin" != userName {
return errors.New("不是超级用户,不能打开数据库....")
}
fmt.Println("超级用户成功打开数据库.....")
return nil
}
// SupperUser 超级用户
func SupperUser() {
err := OpenDb("admin")
if nil != err {
panic(err)
}
fmt.Println("超级用户打开数据库之后的操作.......")
}
func main() {
OpenDb("admin")
fmt.Println("超级用户打开数据库之后的操作.......")
}
输出结果:
超级用户成功打开数据库.....
超级用户打开数据库之后的操作.......
主程序之后的操作........
示例代码如下(发生错误时):
// OpenDb 超级用户打开数据库方法
func OpenDb(userName string) (err error) {
if "admin" != userName {
return errors.New("不是超级用户,不能打开数据库....")
}
fmt.Println("超级用户成功打开数据库.....")
return nil
}
// SupperUser 超级用户
func SupperUser() {
err := OpenDb("Super")
if nil != err {
panic(err)
}
fmt.Println("超级用户打开数据库之后的操作.......")
}
func main() {
OpenDb("admin")
fmt.Println("超级用户打开数据库之后的操作.......")
}
我们将SupperUser() 方法中的OpenDb(“admin”)改成了OpenDb(“Supper”)
运行结果:
panic: 不是超级用户,不能打开数据库....
goroutine 1 [running]:
main.SupperUser()
C:/workplace/go/src/selftPro/TextStr.go:35 +0x7d
main.main()
C:/workplace/go/src/selftPro/TextStr.go:42 +0x19
Process finished with the exit code 2
程序发生了错误,并终止了程序。
总结
以上这些内容就是本次要和大家分享的,golang错误处理的功能强大,这里只是冰山一角,更高级的用法还有待大家自行挖掘,感谢!!!