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)

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

相关推荐
明月_清风17 小时前
Go语言空接口与类型断言完全指南:从"万能容器"到"类型还原"
后端·go
蓝宝石的傻话20 小时前
security-collector-exporter:用Prometheus 解决 Linux 的安全审计
go
tyung21 小时前
Go 手写二叉堆优先队列:避开 container/heap 的性能陷阱
数据结构·后端·go
审判长烧鸡2 天前
【PHPer转Go】fmt vs log/slog
go·php
漓漾li2 天前
每日面试题(2026-05-20)- GO AI agent全栈
后端·架构·go
.魚肉2 天前
Raft 共识算法 · 演示系统(多终端)
算法·go·raft·分布式系统
审判长烧鸡2 天前
【Go工具】go-playground除了validator还有哪些常用的库
go·web
审判长烧鸡2 天前
Go 新版核心知识点合集(适配 Go1.18+ 含泛型 + 断言 + 接口 + 指针接收者全套)
go
审判长烧鸡2 天前
【Go工具】Go 标准库 VS go-playground
go
审判长烧鸡3 天前
【Go 时间类型】时间对比
go·时间