新闻中心
Go如何将多种错误类型统一封装_Go Error统一封装策略
Go中统一错误封装的核心是定义含错误码、消息、时间戳、原始错误等字段的自定义AppError结构体,实现Error()、Unwrap()、Is()方法,并通过New/Wrap/Wrapf函数统一封装,确保错误可识别、可分类、可追踪。

Go 中统一错误封装的核心是定义自定义错误类型,结合错误码、上下文信息和原始错误链,让错误可识别、可分类、可追踪,而不是简单用 fmt.Errorf 堆叠字符串。
定义结构化错误类型
用 struct 封装错误,包含错误码、消息、时间戳、调用栈(可选)和原始错误(Unwrap 支持):
- 错误码建议用
iota枚举,便于判断和国际化 - 实现
Error()方法返回用户友好消息 - 实现
Unwrap()返回底层 err,保持错误链完整 - 可选实现
Is()或As()方便类型断言
示例:
type Code int
const (
CodeOK Code = iota
CodeNotFound
CodeInvalidParam
CodeInternal
)
type AppError struct {
Code Code
Message string
Time time.Time
Err error // 原始错误,用于 Unwrap
}
func (e *AppError) Error() string {
return e.Message
}
func (e *AppError) Unwrap() error {
return e.Err }
func (e *AppError) Is(target error) bool {
if t, ok := target.(*AppError); ok {
return e.Code == t.Code
}
return false
}
封装错误的常用方式
避免裸写 errors.New 或 fmt.Errorf,统一走封装函数:
-
New(code Code, msg string):新建基础错误(无原始错误) -
Wrap(err error, code Code, msg string):包装已有错误,保留上下文和原始错误链 -
Wrapf(err error, code Code, format string, v...any):带格式化消息的包装 - 所有函数返回
*AppError,确保类型一致
这样上层可用 errors.Is(err, ErrNotFound) 判断,也可用 errors.As(err, &e) 提取结构体字段。
分层错误处理与日志协同
不同层级职责分明:
- 底层(如 DB、HTTP client)只返回原始错误或简单包装(如
os.PathError) - 业务层统一用
Wrap转为*AppError,补充业务码和语义化消息 - API 层根据错误码映射 HTTP 状态码,并隐藏敏感细节(如不把数据库错误直接透出)
- 日志中间件自动提取
*AppError的 Code、Message、Time,并记录 stack(若启用了)
例如:DB 查询失败 → 封装为 Wrap(err, CodeNotFound, "user not found") → API 返回 404 + {"code": "NOT_FOUND"}。
避免常见陷阱
- 不要在封装时丢弃原始错误(即不设
Err字段),否则丢失调试线索 - 不要用字符串匹配判断错误类型(如
strings.Contains(err.Error(), "timeout")),应靠errors.Is或errors.As - 不要过度嵌套封装(如 Wrap 三层以上),每层应有明确语义,否则难以定位根因
- 错误码命名建议用大写蛇形(
CODE_INVALID_INPUT)或常量组,避免魔法数字
基本上就这些。统一封装不是为了“看起来高级”,而是让错误真正可查、可分、可控 —— 写起来多几行,维护时省半天。
以上就是Go如何将多种错误类型统一封装_Go Error统一封装策略的详细内容,更多请关注其它相关文章!
# 已有
# 赣州市seo企业
# 长安怎么网站推广外包
# 网站推广图片软件免费
# 关于网站建设方案书实例
# 外贸营销推广公司邯郸
# 阿里网站建设情况
# 七夕抽奖关键词排名
# 网页关键词广告排名
# 网站建设临时保姆
# 装饰网站免费推广
# 半天
# 相关文章
# go
# 如何在
# 可选
# 自定义
# 布尔
# 如何将
# 中统
# 错误码
# 状态码
# ai
# 栈
# app
相关栏目:
【
科技资讯46185 】
【
网络学院92790 】
相关推荐:
谷歌浏览器一键优化方案_谷歌浏览器直达主页极速不卡版
解决Python logging 中 datefmt 导致时间戳固定不变的问题
QQ邮箱官方邮箱登录入口 QQ邮箱网页版快速访问
AO3网页版合集入口 Archive of Our Own同人作品浏览指南
J*a里如何实现线程安全的懒加载单例_懒加载单例实现方法解析
J*aScript Promise链中如何正确终止后续.then执行并处理错误
天眼查怎么看公司融资情况 天眼查企业融资历史查询步骤【攻略】
C++ typeid如何获取类型信息_C++ RTTI运行时类型识别用法
顺丰快递查单号物流信息 顺丰快递小程序查询入口
俄罗斯搜索引擎Yandex指南 附2025年免登录官网入口
淘宝网网页版登录入口 淘宝官方网页版快捷登录
CSS Flexbox与媒体查询:实现响应式布局中元素的并排与堆叠
J*aScript map 迭代中检测空数组元素的有效方法
Archive of Our Own官网直达 AO3最新可用地址一览
c++中的std::forward_list和std::list有什么不同_c++ forward_list与list区别分析
在J*a中如何开发在线活动报名与管理系统_活动报名管理项目实战解析
Yandex搜索引擎官网入口_俄罗斯Yandex免登录一键直达
c++ 命名空间怎么用 c++ namespace使用指南
windows10怎么查看硬盘序列号_windows10硬盘id查询命令
AI泡沫首次被“刺破”:GPU十年都无法存活!
Lar*el 8 多关键词数据库搜索优化实践
探索高级语言到原生C/C++的转译:挑战与内存管理策略
基于动态规划的房屋花卉种植最小成本算法详解
qq邮箱日历功能怎么用_创建日程与会议邀请的技巧
J*aScript设计模式实践_j*ascript代码优化
在Go语言中利用后缀数组处理多字符串:实现高效文本匹配与自动补全
漫蛙漫画登录站点 漫蛙2正版漫画快速访问
谷歌google账号怎么注册账号 谷歌账号注册官方流程
自定义Bag-of-Words实现:处理带负号的词汇权重
QQ邮箱登录平台入口 QQ邮箱网页版邮箱官方入口
Win11怎么合并任务栏图标 Win11开启任务栏合并减少图标占空间【方法】
Go语言中Map存储的结构体如何调用指针方法:深入解析与实践
Go语言中JSON数据解析与字段访问教程
顺丰快递查询系统 官方正版查询入口
《明末:渊虚之羽》设计师谈设计角色:那会刚毕业 充满激情
composer 和 npm/yarn 在管理依赖方面有什么核心思想差异?
CSS Grid如何控制元素对齐_align-items与justify-items组合使用
Fabric模组开发:自定义物品与物品组的现代管理方法
解决移动端滚动问题的overflow属性应用指南
创客贴用户入口官网登录 创客贴网页版电脑版系统
Mac终端命令大全_Mac常用Terminal指令速查
Go调试环境为何无法启动_Go调试器启动失败原因与解决策略
word邮件合并后日期格式不对怎么改_Word邮件合并日期格式修改方法
微信网页版扫码登录入口 微信网页版二维码登录入口
FullCalendar 自定义按钮样式定制指南
Lar*el头像管理:图片缩放与旧文件删除的最佳实践
抖音网页版快捷访问 抖音网页版网页版入口操作教程
12306选座如何查看座位示意图_12306座位示意图解读与使用
PHP中获取MongoDB服务器运行时间(Uptime)的专业指南
Python模块化编程:有效管理依赖与避免循环引用


2025-12-15
浏览次数:次
返回列表
return e.Err }
func (e *AppError) Is(target error) bool {
if t, ok := target.(*AppError); ok {
return e.Code == t.Code
}
return false
}