V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
The Go Programming Language
http://golang.org/
Go Playground
Go Projects
Revel Web Framework
atVoid
V2EX  ›  Go 编程语言

Go 优雅的错误处理: 支持错误码, 错误堆栈, 错误链的工具库

  •  
  •   atVoid ·
    morrisxyang · 2023-07-11 14:16:38 +08:00 · 1339 次点击
    这是一个创建于 505 天前的主题,其中的信息可能已经有所发展或是发生改变。

    https://github.com/morrisxyang/errors

    在业务开发中需要一个支持错误码对外返回, 堆栈打印等能力的错误工具库, 先开始使用 pkg/errors, 但该项目已经只读, 上次更新是几年前, 而且有一些点比如调整堆栈打印深度, 打印格式等能力没有支持, 后续根据业务的需要抽取了一个通用库, 做了一些优化, 详见下方.

    如果觉得有用欢迎 Star 和 PR, 有问题请直接提 issue

    errors

    Go Reference Static Badge Coverage Status Go Report Card Static Badge

    简单的支持错误堆栈, 错误码, 错误链的工具库:

    • 支持携带堆栈, 嵌套构造错误链

    • 支持携带错误码, 方便接口返回

    • 支持自定义堆栈打印深度和错误链打印格式

    • 使用 CallersFrames 替代 FuncForPC 生成堆栈, 避免特殊情况line number 错误等问题, 详见runtime: strongly encourage using CallersFrames over FuncForPC with Callers result

    • 简化堆栈信息, 一条链路多次Wrap操作只保留最深层堆栈, 只打印一次

    安装和文档

    安装使用 go get github.com/morrisxyang/errors

    文档地址是 https://pkg.go.dev/github.com/morrisxyang/errors

    快速开始

    构造错误链

    func a() error {
    	err := b()
    	err = Wrap(err, "a failed reason")
    	return err
    }
    
    func b() error {
    	err := c()
    	err = Wrap(err, "b failed reason")
    	return err
    }
    
    func c() error {
    	_, err := os.Open("test")
    	if err != nil {
    		return WrapWithCode(err, 123, "c failed reason")
    	}
    	return nil
    }
    

    打印错误信息, %+v会打印堆栈, %v只打印错误信息

    a failed reason
    Caused by: b failed reason
    Caused by: 123, c failed reason
    Caused by: open test: no such file or directory
    github.com/morrisxyang/errors.c
    	/Users/morrisyang/Nutstore Files/go-proj/githuberrors/errors_test.go:94
    github.com/morrisxyang/errors.b
    	/Users/morrisyang/Nutstore Files/go-proj/githuberrors/errors_test.go:86
    github.com/morrisxyang/errors.a
    	/Users/morrisyang/Nutstore Files/go-proj/githuberrors/errors_test.go:80
    ....堆栈信息省略
    

    核心方法

    错误封装

    错误解析

    配置

    FAQ

    1. 多次 Wrap 错误会携带多次堆栈吗?

      可在调用链路上多次 Wrap, 添加说明信息, 但只有最深层的 Wrap 操作会设置堆栈, 继续 Wrap, return err 等操作不会影响堆栈信息

    2. 在链路中某个错误设置了合适的错误码, 然后继续 Wrap 时没有设置, 如何获取?

      建议在合适的清晰的时机设置有效的错误码, 可以使用EffectiveCode获取链路中外层第一个有效的非 0 错误码, 由于系统调用等情况, 同一链路中可能有多个错误携带错误码, 此时默认外层的错误码应该对外暴露, 屏蔽了内层的详细信息.

    4 条回复    2023-07-19 18:45:25 +08:00
    tairan2006
        1
    tairan2006  
       2023-07-11 17:49:23 +08:00
    标准库里面内置的就有 errors 啊
    atVoid
        2
    atVoid  
    OP
       2023-07-13 14:12:15 +08:00
    @tairan2006
    标准库的 errors 没有堆栈, 这里主要是增加了堆栈, 以及微服务常用的错误码等支持
    tairan2006
        3
    tairan2006  
       2023-07-13 16:22:19 +08:00   ❤️ 1
    @atVoid #2 我的意思是,你的包名能不能换一个…
    atVoid
        4
    atVoid  
    OP
       2023-07-19 18:45:25 +08:00
    @tairan2006 啊, 确实, 我知道了. 我想想
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   5549 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 01:28 · PVG 09:28 · LAX 17:28 · JFK 20:28
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.