{"id":23447527,"url":"https://github.com/cmstar/go-errx","last_synced_at":"2026-02-12T02:09:52.523Z","repository":{"id":57644373,"uuid":"439799077","full_name":"cmstar/go-errx","owner":"cmstar","description":"提供一组类型与方法，用于将错误信息封装起来形成错误链，以便在程序中更精准的定位和跟踪错误。","archived":false,"fork":false,"pushed_at":"2025-02-12T07:03:26.000Z","size":67,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-09-03T05:44:20.459Z","etag":null,"topics":["error-handling","error-tracking","errors","go","go-library","golang"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/cmstar.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-12-19T07:10:40.000Z","updated_at":"2025-02-12T07:03:29.000Z","dependencies_parsed_at":"2025-02-15T16:42:25.628Z","dependency_job_id":"ae98ba25-2a0a-4e62-8b6d-5dbb2291bfec","html_url":"https://github.com/cmstar/go-errx","commit_stats":null,"previous_names":[],"tags_count":10,"template":false,"template_full_name":null,"purl":"pkg:github/cmstar/go-errx","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cmstar%2Fgo-errx","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cmstar%2Fgo-errx/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cmstar%2Fgo-errx/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cmstar%2Fgo-errx/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/cmstar","download_url":"https://codeload.github.com/cmstar/go-errx/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cmstar%2Fgo-errx/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29354713,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-12T01:03:07.613Z","status":"online","status_checked_at":"2026-02-12T02:00:06.911Z","response_time":55,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["error-handling","error-tracking","errors","go","go-library","golang"],"created_at":"2024-12-23T21:18:04.362Z","updated_at":"2026-02-12T02:09:52.510Z","avatar_url":"https://github.com/cmstar.png","language":"Go","readme":"# errx - 更精准的定位和跟踪错误\n\n[![GoDoc](https://pkg.go.dev/badge/github.com/cmstar/go-errx)](https://pkg.go.dev/github.com/cmstar/go-errx)\n[![Go](https://github.com/cmstar/go-errx/workflows/Go/badge.svg)](https://github.com/cmstar/go-errx/actions?query=workflow%3AGo)\n[![codecov](https://codecov.io/gh/cmstar/go-errx/branch/master/graph/badge.svg)](https://codecov.io/gh/cmstar/go-errx)\n[![License](https://img.shields.io/badge/license-MIT-brightgreen.svg?style=flat)](https://opensource.org/licenses/MIT)\n[![GoVersion](https://img.shields.io/github/go-mod/go-version/cmstar/go-errx)](https://github.com/cmstar/go-errx/blob/main/go.mod)\n[![Go Report Card](https://goreportcard.com/badge/github.com/cmstar/go-errx)](https://goreportcard.com/report/github.com/cmstar/go-errx)\n\n功能：\n- 封装引起错误的错误。\n- 为错误追加方法调用栈信息。\n- 业务预定义异常 `BizError` 。\n- 用于处理 recover() 结果的 `PreserveRecover` 方法。\n\n安装：\n```\ngo get -u github.com/cmstar/go-errx@latest\n```\n\n## 调用栈和错误链\n\nGo 程序通常小而精，更多的用于中间件和系统编程，但有时仍会被用在上层的复杂业务里，和 Java 、 .net 同台，此时 Go 的错误处理模式就变得捉襟见肘起来。也许这就不是 Go 的设计意图，但真实的编码场景里，我们免不了碰到这样的情况。\n\nGo 的 error 只是“不太特殊”的值而已（[Errors are values](https://go.dev/blog/errors-are-values)），它太过于普通以至于不能像 Java/.net 的 `Exception` 一样携带足够多的信息。\n\n在复杂的上层业务中，快速定位错误的位置显得极为重要，有时可以用运行性能换工作效率。\n\n---\n\n### Wrap 方法\n\n`errx.Wrap` 为错误添加更多的细节，返回一个 `StackfulError` 接口的实现，它包含方法：\n- Cause：记录引起错误的错误，类似 Java 的 `Throwable.getCause()` 或 .net 的 `Exception.InnerException` 。\n- Stack：记录创建错误（即调用 Wrap 方法）时的方法调用栈，类似 Java 的 `Exception.printStackTrace()` 或 .net 的 `Exception.StackTrace` 。\n- Error：即标准库的 `error.Error()` ，但它包含了 `Cause` 和 `Stack` 格式化后的信息。输出格式见下文《Describe 方法》。\n- ErrorWithoutStack：只包含错误的描述，不包含 `Stack` 的信息。\n\n\u003e 调用栈信息使用标准库的 `runtime.CallersFrames` 方法获取，有一定的性能开销。\n\n## BizError\n\n在业务交互中，我们可能需要根据错误的类别进行不同的处理，原始的 `error` 等同于一个字符串，难以判断和分类。 errx 包定义了 `BizError` ，以便对错误进行分类。它是一个特殊的 `error` ，可通过 `errx.NewBizError` 方法创建。\n\n`BizError` 提供：\n- 为每个错误添加一个整数型的错误码 `Code` ，以便更精准的对错误进行分类和定位，特别是在日志搜索时。通常0表示没有错误，其余值表示有错误，值由具体业务指定。\n- 包含调用栈信息 `Stack` 。\n- 包含 `Cause` ，即引起此错误的错误。\n\n`BizError.Error()` 返回值格式为： `(Code) Message` ，不包含 `Cause` 和 `Stack` 。\n\n`BizError` 的使用样例可参考 [GoDoc 示例](https://pkg.go.dev/github.com/cmstar/go-errx#example-BizError) 。\n\n\u003e [go-webapi](https://github.com/cmstar/go-webapi#%E9%94%99%E8%AF%AF%E5%A4%84%E7%90%86) 框架使用 `BizError` 区分需要返回的业务错误和其他内部错误。\n\n## 方法\n\n### Describe 方法\n\n`errx.Describe` 将 `errx.Wrap` 添加的信息抽取出来，形成一段完整的错误描述，它包含各层级错误的信息及调用栈。\n\n格式为：\n```\n最外层错误描述\n--- 最外层错误的调用栈信息\n=== 第1层内部错误的描述\n--- 第1层内部错误的调用栈信息\n=== 第2层内部错误的描述\n--- 第2层内部错误的调用栈信息\n...（逐层展示）\n=== 最内层错误的描述\n--- 最内层错误的描述的调用栈信息\n```\n\n实际示例可参考 [GoDoc 示例](https://pkg.go.dev/github.com/cmstar/go-errx#example-package-ErrorChain) 。\n\n---\n\n总体而言，就是让 Go 的 `error` 更像 Java/.net 的 `Exception` 。\n\n当一个 `error` 在 `Wrap` 之后返回给其调用者，调用者再次使用 `Wrap` 并返回给更上层的调用者， error 就形成了一个链条。\n\n### PreserveRecover 方法\n\n我们可能需要利用应对 `panic` ，并将相关的错误信息保留下来，代码如下：\n\n```go\nfunc do() (err error) {\n    defer func() {\n        r := recover()\n        if r == nil {\n            return\n        }\n\n        // 留存错误，丢失了调用栈信息。\n        err = fmt.Errorf(\"do: %v\", r)\n    }()\n\n    somethingThatMayPanic()\n    return nil\n}\n```\n\n利用 `PreserveRecover` 方法，这段代码可以简化成这样，当 `recover()` 的结果不是 `nil` 时，它会被 `Wrap()` 在一个错误里：\n\n```go\nfunc do() (err error) {\n    defer func() {\n        // 留存错误，并保留调用栈信息。若 recover() 结果为 nil ，则 err 也是 nil 。\n        err = errx.PreserveRecover(\"do\", recover())\n    }()\n\n    somethingThatMayPanic()\n    return nil\n}\n```\n\n### Run/RunE 方法\n\n用于执行一个可能会 panic 的方法，自动添加 `defer` 过程，并通过 `PreserveRecover` 方法捕获错误。\n\n```go\nfunc do() {\n    err := errx.Run(func() {\n        panic(\"oops!\")\n    })\n    fmt.Println(err)\n}\n\n```","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcmstar%2Fgo-errx","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcmstar%2Fgo-errx","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcmstar%2Fgo-errx/lists"}