1. 错误处理机制
1.1 先看一段代码,引出Golang错误处理机制
看到了上面的代码后,思考两个问题?
(1)有没有办法,能让test()执行出错了,它下面的fmt代码依然能够运行。
(2)即使出错,能不能发出提醒,并给出预警机制(如通知到具体的人)。
1.2 关于golang的错误处理
- Go在默认情况下,当发生错误后,程序会panic并退出运行(崩溃)。
- 如果希望,发生错误后,可以捕获到错误,并进行处理,且保证代码还能继续往下执行。甚至还能再捕获到错误后,给管理员一个提示(邮件、短信等)。
- 这里将引出go的错误处理机制。
1.3 基本说明
(1)Go语言追求简洁,所以不支持传统的try…catch…finally这种错误处理机制。
(2)Go中引入的错误处理方式为:defer、panic、recover。
(3)这几个异常使用的场景可以简单理解为:Go中报错一个panic异常,然后defer中通过recover捕获到这个异常,然后进行正常处理。
也就是说,panic、defer、recover三者是结合使用的。
2. 错误处理(panic后继续运行)
2.1 使用defer+recover处理和捕获异常(panic)
package main
import "fmt"
func test() {
// 定义一个捕获异常的匿名函数
defer func() {
err := recover() // recover是内置函数,可以捕获到异常
if err != nil {
fmt.Println("err=", err)
}
}()
num1 := 10
num2 := 0
res := num1 / num2
fmt.Println("res=", res)
}
func main() {
test()
fmt.Println("下面的代码和逻辑:")
}
============终端执行============
PS D:\个人\GO开发\20240624> go build main.go
PS D:\个人\GO开发\20240624> .\main.exe
err= runtime error: integer divide by zero // 报错了
下面的代码和逻辑: // 但是test()函数下面的代码依然执行了,说明程序没有因为panic而崩溃
2.2 错误处理的好处
进行错误处理后,程序不会轻易的挂掉,如果加入预警代码,还能让程序更加的健壮。
如下代码演示:
3. 自定义错误
在Go中,可以使用errors.New方法和panic内置函数来自定义错误。
- errors.New(“错误内容”),会返回一个error类型(是个接口)的值,表示一个错误。
- panic内置函数,接受一个any类型的值作为参数。可以接收error类型的变量,输出错误信息,并退出运行。
3.1 案例演示:检测文件名
3.1.1 文件名错误
package main
import (
"errors"
"fmt"
)
// 读取配置文件init.conf的信息,如果文件名传入不正确,就返回一个自定义的错误
func readConf(name string) (err error) {
if name == "init.conf" {
// 读取
return nil // nil表示读取成功,没有错误
} else {
// 返回自定义错误
return errors.New("读取文件名错误...")
}
}
func test() {
err := readConf("config.init") //这里传入了一个错误的文件名测试
if err != nil {
// 如果读取文件失败,就输出错误,并终止程序继续运行。
panic(err)
}
fmt.Println("test函数调用成功,且后续代码继续执行")
}
func main() {
test()
fmt.Println("test函数后续的代码!!!")
}
============终端执行============
PS D:\个人\GO开发\20240624> go build main.go
PS D:\个人\GO开发\20240624> .\main.exe
panic: 读取文件名错误...
goroutine 1 [running]:
main.test()
D:/个人/GO开发/20240624/main.go:23 +0x49
main.main()
D:/个人/GO开发/20240624/main.go:29 +0x19
3.1.2 正确的文件名
package main
import (
"errors"
"fmt"
)
// 读取配置文件init.conf的信息,如果文件名传入不正确,就返回一个自定义的错误
func readConf(name string) (err error) {
if name == "init.conf" {
// 读取
return nil // nil表示读取成功,没有错误
} else {
// 返回自定义错误
return errors.New("读取文件名错误...")
}
}
func test() {
err := readConf("init.conf") // 这里改为正确的文件名
if err != nil {
// 如果读取文件失败,就输出错误,并终止程序继续运行。
panic(err)
}
fmt.Println("test函数调用成功,且后续代码继续执行")
}
func main() {
test()
fmt.Println("test函数后续的代码!!!")
}
============终端执行============
PS D:\个人\GO开发\20240624> go build main.go
PS D:\个人\GO开发\20240624> .\main.exe
test函数调用成功,且后续代码继续执行
test函数后续的代码!!!