GO错误处理【5】显式错误处理

按照上一章的说法,我所有的函数方法都要后面加一个err?

要不然没法一层一层往上传递?

你抓到 Go 语言的"命脉"了!是的,在 Go 赛道,几乎所有涉及 IO、数据库、网络或复杂业务的函数,标配都是返回 (数据, error)。

这确实和 PHP 习惯"直接返回数据,出事抛异常"不一样。在 Go 里,这叫"显式错误处理"。

1. 为什么要一层层往上交?

想象你在 PHP 里:

复制代码
// PHP 逻辑
function getInfo() {
    return $db->query(); // 如果这里崩了,直接炸到顶层,中间的逻辑管不住
}

而在 Go 里,这就是一场接力赛:

  • Repo 层:拿到最原始的错,包一下,交给 Logic。
  • Logic 层:看看这个错能不能救(比如读缓存),救不了,再包一下上下文,交给 Handler。
  • Handler 层:最后拍板,是给用户看"系统维护",还是记录一条"严重报警"。

如果没有每一层后面的 error,这个接力棒就断了,顶层根本不知道底层发生了什么,也就没法写出有意义的日志。

2. 难道所有函数都要加 err 吗?

不一定。你可以根据"有没有可能失败"来判断:

  • 需要加 err 的(涉及外部环境):
    • 查数据库、读写文件、调远程接口、解析 JSON、字符串转数字。
    • 准则:只要这个函数依赖"运气"(环境、网络、用户输入),就得带 err。
  • 不需要加 err 的(纯逻辑运算):
    • 计算两个数之和、拼接两个字符串、从结构体里取一个已经存在的字段。
    • 准则:只要这个函数是"确定性"的,给同样的输入一定有同样的输出,就不需要 err。

3. 写起来会不会很累?

刚开始你会觉得 if err != nil 写得手酸,但你会发现这种写法带来的安全感:

  1. 没有隐藏炸弹:你盯着代码看,哪里有 err 哪里就有风险,一目了然,不需要猜哪里会抛异常。
  2. 强制思考:Go 强制你面对错误。PHP 里你可能会忘了 try-catch,但 Go 里如果你忽略了返回的 err,编译器或静态检查工具会跳出来提醒你。

4. 报错链条实战总结

你可以把这套公式背下来:

  1. 底层 (Repo): return nil, fmt.Errorf("repo context: %w", err)
  2. 中层 (Logic): return nil, fmt.Errorf("logic context: %w", err)
  3. 顶层 (Handler): infra.Log("api").Error("final message", "err", err)

这就是你之前担心的"日志白写了"的终极答案: 底层和中层只负责"攒信息",顶层负责"按开关写日志"。

相关推荐
Thinker QAQ11 小时前
并发编程(九):BlockingQueue 与 Channel——语言层的原子性、可见性与有序性
java·python·go·并发编程·channel·blockingqueue·message passing
茉莉玫瑰花茶18 小时前
GO [ 标准库 · unsafe ]
后端·go
人人都是软件工程师1 天前
17-反射:在运行时观察和操作类型
go
人人都是软件工程师1 天前
19-context 包详解:让并发任务可取消、可超时
go
miofly1 天前
GitHub 今日推荐|open_scion:为AI代理设计的并发版本控制
开源·go·github
敲代码的玉米C2 天前
编辑器开始懂 Git:改动、提交图和 worktree
go
敲代码的玉米C2 天前
我想用 Go 写个编辑器,先把「轻量」这件事想明白
go
敲代码的玉米C2 天前
让工作流接起来:文件拖放与 Git 冲突处理
go
敲代码的玉米C2 天前
中文输入不是「能打出汉字」就算完成
go
敲代码的玉米C2 天前
把熟悉的操作带回来:快捷键和 Markdown 预览
go