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。
相关推荐
审判长烧鸡2 小时前
GO时区【4】PostgreSQL时区
postgresql·go
审判长烧鸡3 小时前
GO时区【3】字段与连接设置
postgresql·go
审判长烧鸡4 小时前
GO错误处理【1】不用try-catch用什么?
go·异常处理·try-catch·panic·fatal·os.exit
Go_error2 天前
Go database/sql 基于临时 channel 传递连接
后端·go
Go_error2 天前
Go 循环栅栏
后端·go
wecode662 天前
一个可以复现整个日志系统演进过程的工程级 specification
go·日志系统
程序设计实验室2 天前
当 CGO 遇见 Zig:一种更优雅的折腾方式,对比 GCC 后端
go
小熊吃保安3 天前
Excel下载变成了ZIP?Docker 容器里的 Content-Type 离奇失踪案
docker·go
Coding君3 天前
每日一Go-58、NATS 如何做到高可用?NATS集群部署方式来了
go