{"record":{"id":"3b3c461763a8ee0b","repo":"unknwon/the-way-to-go_ZH_CN","slug":"things-aren-t-good","errorCode":null,"errorMessage":"things aren’t good","messagePattern":"things aren’t good","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"info","filePath":"eBook/16.10.md","lineNumber":16,"sourceCode":"# 16.10 糟糕的错误处理\n\n译者注：该小结关于错误处理的观点，译者并不完全赞同，关于本小结的部分想法请参考 [关于 16.10.2 小节错误处理的一些见解](Discussion_about_16.10.md)。\n\n\n依附于[第 13 章](13.0.md)模式的描述和[第 17.1 小节](17.1.md)与[第 17.2.4 小节](17.2.md)的总结。\n\n## 16.10.1 不要使用布尔值：\n\n像下面代码一样，创建一个布尔型变量用于测试错误条件是多余的：\n\n```go\nvar good bool\n    // 测试一个错误，`good` 被赋为 `true` 或者 `false`\n    if !good {\n        return errors.New(\"things aren’t good\")\n    }\n```\n\n立即检测一个错误：\n\n```go\n... err1 := api.Func1()\nif err1 != nil { … }\n```\n\n## 16.10.2 避免错误检测使代码变得混乱：\n\n避免写出这样的代码：\n\n```go\n... err1 := api.Func1()\nif err1 != nil {\n    fmt.Println(\"err: \" + err.Error())","sourceCodeStart":1,"sourceCodeEnd":34,"githubUrl":"https://github.com/unknwon/the-way-to-go_ZH_CN/blob/7a54d34d3657084b6a59e5618bd069b912d571aa/eBook/16.10.md#L1-L34","documentation":"Textbook anti-pattern, shown deliberately so the book can say 'don't do this': a boolean good is set by testing an error condition, and then !good converts it back into a fresh errors.New(\"things aren’t good\"). The illustrated problem: re-encoding an error you already have into a vaguer one discards the original cause; the correct move, shown right below, is to test the error value directly (if err1 != nil { ... }).","triggerScenarios":"Only appears if you copy this shape into your code: an api.Func1()-style call whose error is squeezed into good bool, and !good then produces this stringly error. At runtime it fires whenever the underlying operation failed — with all diagnostic detail stripped.","commonSituations":"Wrapper layers that reduce errors to booleans (ok flags from internal helpers); legacy success-flag APIs; test helpers that report only pass/fail and then stringify; debug sessions where the root cause is unrecoverable because this message replaced it.","solutions":["Delete the boolean entirely and propagate the original error: if err := api.Func1(); err != nil { return err }","If a boolean API must stay, carry the error alongside it (ok bool, err error) and never synthesize a new message","When adding context, wrap rather than replace: return fmt.Errorf(\"calling Func1: %w\", err)","Add lint guardrails: errcheck and staticcheck flag the ignored errors that push code toward this pattern"],"exampleFix":"// before\nvar good bool\n// an error is tested; good becomes true or false\nif !good {\n\treturn errors.New(\"things aren’t good\") // original cause lost\n}\n\n// after (the book's recommendation: check the error immediately)\nif err1 := api.Func1(); err1 != nil {\n\treturn fmt.Errorf(\"func1 failed: %w\", err1)\n}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"// capture the error where it is produced; do not re-encode it into a bool\nif err := api.Func1(); err != nil {\n\treturn fmt.Errorf(\"func1: %w\", err)\n}","preventionTips":["Never collapse an error into a success bool at an API boundary; pass (bool, error) pairs if a flag is truly needed","Wrap with %w rather than minting new errors.New messages that drop the cause","Enable errcheck/staticcheck in CI to catch ignored errors that push code toward bool workarounds","When reviewing legacy ok-flag APIs, add error returns before adding new callers"],"tags":["go","anti-pattern","error-handling","code-style"],"backgroundTag":null,"analyzedSha":"7a54d34d3657084b6a59e5618bd069b912d571aa","analyzedAt":"2026-08-15T15:13:06.026Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}