{"record":{"id":"1b3f143fe05ae155","repo":"unknwon/the-way-to-go_ZH_CN","slug":"not-found-error","errorCode":null,"errorMessage":"Not found error","messagePattern":"Not found error","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"info","filePath":"eBook/13.1.md","lineNumber":34,"sourceCode":"\n```go\nerr := errors.New(\"math - square root of negative number\")\n```\n\n在示例 13.1 中你可以看到一个简单的用例：\n\n示例 13.1 [errors.go](examples/chapter_13/errors.go)：\n\n```go\n// errors.go\npackage main\n\nimport (\n\t\"errors\"\n\t\"fmt\"\n)\n\nvar errNotFound error = errors.New(\"Not found error\")\n\nfunc main() {\n\tfmt.Printf(\"error: %v\", errNotFound)\n}\n// error: Not found error\n```\n\n可以把它用于计算平方根函数的参数测试：\n\n```go\nfunc Sqrt(f float64) (float64, error) {\n\tif f < 0 {\n\t\treturn 0, errors.New (\"math - square root of negative number\")\n\t}\n   // implementation of Sqrt\n}\n```\n","sourceCodeStart":16,"sourceCodeEnd":52,"githubUrl":"https://github.com/unknwon/the-way-to-go_ZH_CN/blob/7a54d34d3657084b6a59e5618bd069b912d571aa/eBook/13.1.md#L16-L52","documentation":"Package-level sentinel error from section 13.1's errors.go example: var errNotFound error = errors.New(\"Not found error\"). It demonstrates the Go idiom of declaring one shared error value at package scope so every lookup miss returns the identical value, letting callers compare with err == errNotFound (or errors.Is) instead of matching message text. The example main only prints it (fmt.Printf(\"error: %v\", errNotFound)).","triggerScenarios":"The printed demo never fires it; it becomes a runtime error once you follow the book's next step and return errNotFound from a lookup function when the sought key/element is absent — e.g. the Sqrt parameter test or a map/slice Find that reaches its miss branch.","commonSituations":"Key lookups in caches and config maps; repository-style Find functions returning (T, error); the classic beginner mistake of declaring the sentinel inside the function (new allocation per call) so == comparison stops working; keeping it lowercase (errNotFound) so other packages cannot reference it.","solutions":["Keep the declaration at package level exactly as shown so identity comparison works, and export it (ErrNotFound) if callers live in another package","Compare with errors.Is(err, ErrNotFound), never by string, so wrapping with %w still matches","Return the same sentinel from every miss path in the package so callers have exactly one case to handle","If the message appears unexpectedly in logs, audit callers that print err without distinguishing not-found from real failures"],"exampleFix":"// before: sentinel trapped inside the function, new value each call\nfunc Find(k string) (*Item, error) {\n\terrNotFound := errors.New(\"Not found error\")\n\t// ...\n\treturn nil, errNotFound\n}\n\n// after: one exported package-level sentinel\nvar ErrNotFound = errors.New(\"Not found error\")\n\nfunc Find(k string) (*Item, error) {\n\t// ...\n\treturn nil, ErrNotFound\n}","handlingStrategy":"type-guard","validationCode":null,"typeGuard":"var ErrNotFound = errors.New(\"Not found error\")\n\nfunc IsNotFound(err error) bool {\n\treturn errors.Is(err, ErrNotFound)\n}","tryCatchPattern":"item, err := Find(key)\nif err != nil {\n\tif errors.Is(err, ErrNotFound) {\n\t\t// absence is a normal outcome: empty result, 404, or default\n\t\treturn Item{}, nil\n\t}\n\treturn Item{}, err // real failure\n}","preventionTips":["Declare sentinel errors once at package level, exported if cross-package; never inside the function","Compare with errors.Is or ==, never err.Error() string matching","Wrap with %w when adding context so sentinel checks still succeed","Handle the not-found branch separately from infrastructure failures at every call site"],"tags":["go","sentinel-error","documentation","not-found"],"backgroundTag":null,"analyzedSha":"7a54d34d3657084b6a59e5618bd069b912d571aa","analyzedAt":"2026-08-15T15:13:06.026Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}