Go错误处理
- 输入错误
- 逻辑错误
- 网络故障
- 硬件故障
- 基础组件故障
- 链路调用故障
常见的错误处理方式:
try
可能出错的代码
catch
对错误进行处理
// go中把err作为一种类型
result, err = 代码
if err != nil {
代码出现错误
错误处理
}
普通错误处理
Go 错误处理哲学
Go鼓励通过==返回值==显式传递和处理错误,而不是依赖异常(panic/recover)。只有在不可恢复的严重错误(如数组越界、除零、程序内部bug)时才用panic。
package main
import (
"errors"
"fmt"
)
func safeDivide(num1, num2 int) (int, error) {
if num2 == 0 {
return 0, errors.New("除数不能为0")
}
return num1 / num2, nil
}
func main() {
num1 := 10
num2 := 0
res, err := safeDivide(num1, num2)
if err != nil {
fmt.Println("err=", err.Error())
return
}
fmt.Println("res=", res)
}
极端错误处理
panic: 可以在异常的时候让程序终止执行,退出程序。
- 只有在遇到不可恢复的致命错误时才用 panic/recover,比如程序内部不一致、严重bug等。
- 普通业务逻辑错误(如除零、文件不存在)不影响程序其他部分,应通过 error 返回。
- panic不能滥用,不能到处用panic
panic/recover 机制
- 在默认情况下,当发生错误后(panic) ,程序就会退出(崩溃)
- 如果我们希望:当发生错误后,可以捕获到错误,并进行处理,保证程序可以继续执行。还可以在捕获到错误后,产生某些告警信息等
这就需要对错误进行特殊处理: - Go 语言追求简洁优雅,不支持传统的 try catch finally这种处理。
- Go 中引入的处理方式为:defer, panic, recover。简单描述:抛出一个 panic 的异常,在 defer 中通过 recover 捕获这个异常,然后正常处理。
- recover会阻止panic一层一层传播导致程序崩溃。recover会捕获到panic的报错,尝试恢复程序,不让其终止。recover必须在defer中执行。
package main
import (
"fmt"
)
func test() {
//使用defer + recover 来捕获和处理异常
//defer注册一个延迟调用的匿名函数。
defer func() {
// recover()内置函数,没panic返回nil;有panic返回panic值
if err := recover(); err != nil { // 说明捕获到错误
fmt.Println("err occurred=", err)
//程序不退出,可以继续发出一个告警
//可以记录一条日志
//可以返回给前端说传入的值不对
}
}()
num1 := 10
num2 := 0
res := num1 / num2 //这里有panic。Go 会立即中断当前函数的执行,转而执行已经注册的 defer 语句
fmt.Println("res=", res)
}
func main() {
test()
}
自定义错误
Go 程序中,也支持自定义错误, 使用 errors.New 和 panic 内置函数。
errors.New("错误说明"), 会返回一个 error 类型的值,表示一个错误panic内置函数,接收一个interface{}类型的值(也就是任何值)作为参数。可以接收 error 类型的变量,输出错误信息,并退出程序。
package main
import (
"fmt"
"errors"
)
func readconf(name string) (err error) {
// 读取init.conf配置文件,如果文件名不正确,返回自定义错误
if name == "init.conf"{
return nil
}else{
return errors.New("read file error")
}
}
func test(){
err := readconf("config.ini")
if err != nil{
panic(err)
}
fmt.Println("Continue")
}
func main() {
test()
}
相关笔记: go-基础-05-函数-包 | go-基础-03-变量-数据类型-运算 | go-面向对象 | go-web开发