Error & Panic
错误(Error):指的是程序中预期会发生的结果,预料之中
打开一个文件:文件正在被占用,可知的。
恐慌(Panic):不该出现问题的地方出现了问题,预料之外
调用一个对象,发现这个对象是个空指针对象,发生恐慌。
错误是业务的一部分,而恐慌不是。
1.错误 (Error)
鼓励工程师在代码中显式的检查错误,而非忽略错误。
package main
import (
"fmt"
"os"
)
// 错误是开发中必须要思考的问题
// - 某些系统错误 ,文件被占用,网络有延迟
// - 人为错误:核心就是一些不正常的用户会怎么来给你传递参数,sql注入
func main() {
//打开一个文件 os 系统包,所有可以用鼠标和键盘能执行的事件,都可以用程序实现
// func Open(name string) (*File, error)
file, err := os.Open("aaa.txt")
// 在开发中,我们需要思考这个错误的类型 PathError
// 1、文件不存在 err
// 2、文件被占用 err
// 3、文件被损耗 err
// 调用方法后,出现错误,需要解决
if err != nil {
fmt.Println(err)
return
}
fmt.Println(file.Name())
}
// 在实际工程项目中,
// 我们希望通过程序的错误信息快速定位问题,但是又不喜欢错误处理代码写的冗余而又啰嗦。
// Go语言没有提供像Java. c#语言中的try...catch异常处理方式,
// 而是通过函数返回值逐层往上抛, 如果没有人处理这个错误,程序就终止 panic
// 这种设计,鼓励工程师在代码中显式的检查错误,而非忽略错误。
// 好处就是避免漏掉本应处理的错误。但是带来一个弊端,让代码繁琐。
// Go中的错误也是一种类型。错误用内置的error类型表示。就像其他类型的,如int, float64。
// 错误值可以存储在变量中,从函数中返回,传递参数 等等。
2.自定义错误
errors包
package main
import (
"errors"
"fmt"
)
// 自己定义一个错误
// 1、errors.New("xxxxx")
// 2、fmt.Errorf()
// 都会返回 error 对象, 本身也是一个类型
func main() {
age_err := setAge(-1)
if age_err != nil {
fmt.Println(age_err)
}
fmt.Printf("%T\n", age_err) // *errors.errorString
// 方式二
errInfo1 := fmt.Errorf("我是一个错误信息:%d\n", 500)
//errInfo2 := fmt.Errorf("我是一个错误信息:%d\n", 404)
if errInfo1 != nil {
// 处理这个错误
fmt.Println(errInfo1)
}
}
// 设置年龄的函数,一定需要处理一些非正常用户的请求
// 返回值为 error 类型
// 作为一个开发需要不断思考的事情,代码的健壮性和安全性
func setAge(age int) error {
if age < 0 {
// 给出一个默认值
age = 3
// 抛出一个错误 errors 包
return errors.New("年龄不合法")
}
// 程序正常的结果,给这个用户赋值
fmt.Println("年龄设置成功:age=", age)
return nil
}
3.恐慌(panic)
恐慌(Panic)是一种非常严重的运行时错误,它表示程序发生了无法恢复的错误。当恐慌发生时,程序会立即停止执行,并开始回退调用栈,执行所有被延迟的函数(deferred functions),最后打印出恐慌信息。
恐慌通常是由程序员无法预料的错误条件触发的,例如数组越界、空指针解引用等。在Go语言中,我们可以使用内置的 panic
函数来引发恐慌。
func examplePanic() {
// 引发恐慌
panic("something went wrong")
}
func main() {
defer func() {
if r := recover(); r != nil {
// 恢复从恐慌中恢复,并打印信息
fmt.Println("Recovered:", r)
}
}()
// 调用引发恐慌的函数
examplePanic()
// 不会执行到这里,因为上面的恐慌会导致程序停止执行
fmt.Println("Program continues...")
}
在上面的例子中,panic
函数引发了一个恐慌,而recover
函数用于恢复从恐慌中,通常用在延迟执行的函数中。不过,值得注意的是,通常不鼓励过度使用 panic
和 recover
,而应该通过错误处理来处理可预测的错误。恐慌应该被保留用于处理不可恢复的错误。