GO错误处理【2】os.Exit(1)/panic/返回err的应用场景

可以详细讲一讲什么时候用os.Exit(1),什么时候用panic,什么时候只是返加err?

从 Java/PHP 转到 Go,理解这三者的界限是进阶的核心。Java/PHP 习惯用 try-catch 或直接报错,而 Go 讲究"各司其职"。

1. 什么时候返回 error

场景:99% 的业务逻辑。

在 Go 中,错误被视为正常的数据流。只要是"预料之中"的问题,都应该返回 error

  • 例子:数据库查不到数据、用户密码错误、输入参数不合法、网络请求超时。
  • 原则:不要因为这些事让程序死掉。你应该把 err 一层层往上传,直到 Handler 层,然后调用你写的 res.ApiError 返回给前端。

2. 什么时候用 panic

场景:真正的异常(不该发生的事)。
panic 意味着程序遇到了逻辑死胡同,无法继续执行当前的逻辑。

  • 例子:
    • 代码 Bug:比如访问了 nil 指针、数组越界。
    • 核心环境崩溃:程序运行到一半,发现某个必须存在的配置文件被删了。
  • 处理:在 Web 开发中,我们通常会在最外层用 Recovery 中间件 把 panic 拦住,转成 500 错误,防止整个进程挂掉。

3. 什么时候用 os.Exit(1)

场景:启动即崩溃(初始化阶段)。

这是最狠的一招,直接杀掉进程,不给任何后悔的机会(连 defer 都不会执行)。

  • 例子:main 函数启动时,发现数据库连不上、端口被占用、环境变量没配置。
  • 原则:如果程序的基础设施都不健全,跑起来也是带病工作,不如直接"自杀"。它只应该出现在 main.go 或初始化的那一刻。

4. 必须补上的"保命符":Recovery 中间件

你现在"裸奔"没加 Recovery,万一某个接口的代码写了 a := nil; fmt.Println(a.Name),你的整个后端就直接没了。

建议把这个中间件加在 RequestLogger 之前:

复制代码
// middleware/recovery.go
func Recovery(next http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		defer func() {
			if err := recover(); err != nil {
				// 1. 记录详细的崩溃日志
				infra.Log("panic").Error("程序崩溃了", 
					"err", err, 
					"uri", r.RequestURI,
				)
				
				// 2. 给前端回个 500,别让请求一直挂着
				w.Header().Set("Content-Type", "application/json")
				w.WriteHeader(http.StatusInternalServerError)
				// 这里可以用你之前的 res.ApiError
				json.NewEncoder(w).Encode(map[string]any{
					"code": 500,
					"msg":  "服务器内部错误,请稍后再试",
				})
			}
		}()
		next.ServeHTTP(w, r)
	})
}

总结建议:

  1. 启动时:连不上 DB 这种死罪,用 os.Exit(1)log.Fatal
  2. 写业务时:遇到问题(如查不到用户),一律 return err
  3. 万一写出 Bug:靠 Recovery 中间件兜底,把 panic 变成日志和 500。
相关推荐
用户67570498850219 小时前
你知道 Go 结构体和结构体指针调用的区别吗?一文带你彻底搞懂!
后端·go
唐青枫1 天前
别把泛型写复杂了:Go generic 从类型参数到实战封装
go
GetcharZp1 天前
告别OOM!用Go+libvips实现30000×50000超大图片的流式瓦片服务
后端·go
妙码生花5 天前
从 PHP 到 AI + Golang,程序员自救转型手记(八):设计管理员模型、热重载配置
前端·后端·go
tyung6 天前
Go 手写 Wait-Free MPSC 无界队列:SwapPointer 实现多生产者无锁入队
后端·go
陈明勇6 天前
Go 1.26 新特性回顾:语言增强、工具升级与 Green Tea GC 默认启用
后端·go
妙码生花7 天前
从 PHP 到 AI + Golang,程序员自救转型手记(二):目录结构、初始化 GIT、设计并开发配置系统
前端·后端·go
leeyi7 天前
Deer-Go:字节 Deer-Flow 的 Go 移植,深度研究 Agent 全拆解
go·aigc·agent
Bolt8 天前
TypeScript 7.0 来了:当 tsc 用 Go 重写之后
javascript·typescript·go
Go_error8 天前
Datatypes:Go 轻松支持数据库JSON类型
后端·go