Go 的错误理念:错误也是值
Go 没有 try/catch。函数出错时,把错误作为返回值交还给调用者,由调用者决定怎么处理——这就是 Go 错误处理的核心。
最基本的模式
package main
import (
"errors"
"fmt"
)
func divide(a, b float64) (float64, error) {
if b == 0 {
return 0, errors.New("除数不能为零")
}
return a / b, nil
}
func main() {
r, err := divide(10, 2)
if err != nil {
fmt.Println("出错了:", err)
return
}
fmt.Println("结果:", r) // 输出:结果: 5
}
if err != nil 是 Go 代码里出现频率最高的写法,几乎每个函数调用后都会看到它。
拼变量进错误信息:fmt.Errorf
需要把变量写进错误信息时用 fmt.Errorf,用法和 fmt.Printf 一样:
func checkAge(age int) error {
if age < 0 {
return fmt.Errorf("年龄不合法: %d", age)
}
return nil
}
checkAge(-5) 返回的错误信息是:年龄不合法: -5。
自定义错误类型
想把错误当成"数据"来比对,可以定义自己的错误类型:
type ValidationError struct {
Field string
}
func (e *ValidationError) Error() string {
return "字段校验失败: " + e.Field
}
func validate(age int) error {
if age < 0 {
return &ValidationError{Field: "age"}
}
return nil
}
只要实现了 Error() string 方法,任何类型都是合法的 error。
errors.Is 与 errors.As
Go 1.13 之后,标准库提供了两个判断错误的利器:
var ErrNotFound = errors.New("记录不存在")
func find(id int) error {
return ErrNotFound
}
func main() {
err := find(1)
if errors.Is(err, ErrNotFound) {
fmt.Println("没有找到这条记录") // 输出:没有找到这条记录
}
}
errors.Is:判断错误链里是否包含目标错误(推荐替代==直接比较)errors.As:把错误转换成具体类型,再取出里面的字段
panic 与 recover:最后的手段
程序遇到无法继续运行的严重问题时才用 panic;recover 配合 defer 可以拦截 panic,避免程序崩溃:
func safeRun() {
defer func() {
if r := recover(); r != nil {
fmt.Println("已恢复:", r) // 输出:已恢复: 炸了
}
}()
panic("炸了")
}
func main() {
safeRun()
fmt.Println("程序没有崩溃") // 输出:程序没有崩溃
}
小结
- Go 用返回值传递错误,
if err != nil是标准处理模式 - 临时错误用
errors.New/fmt.Errorf,需要携带数据就定义错误类型 errors.Is判断相等,errors.As提取具体类型- panic 只留给真正无法挽回的场景,正常业务错误一律返回 error
评论 0
还没有评论,来抢沙发吧~ 🛋