不必要,但对关键、可重用、需判断的错误必须定义;仅当错误被多函数返回、需errors.Is/==判断、含义稳定且属公开契约时,才定义包级var错误变量。

是否该为每个错误定义 var 变量?
不必要,但对关键、可重用、需判断的错误必须定义。Go 的错误处理鼓励“按需定义”,不是“按数量定义”。盲目为每个 fmt.Errorf 或 errors.New 都配一个包级变量,反而会增加维护成本和语义模糊性。
哪些错误值得定义为 var?
只在满足以下全部条件时才定义包级错误变量:
- 该错误会被多个函数返回或检查(例如
io.EOF) - 调用方需要通过
errors.Is或==显式判断(如重试逻辑、状态分流) - 错误含义稳定,不随参数动态变化(因此
fmt.Errorf("user %s not found", id)不适合定义为变量) - 属于当前包的公开契约(即导出的
ErrAlreadyClosed),而非内部临时错误
定义方式与常见陷阱
推荐使用 var + errors.New,避免用 fmt.Errorf 初始化变量(后者可能隐含格式化开销且不可比较):
var (
ErrInvalidID = errors.New("invalid user ID")
ErrNotFound = errors.New("resource not found")
ErrAlreadyExists = errors.New("resource already exists")
)
注意:
立即学习“go语言免费学习笔记(深入)”;
函数是一组语句一起执行任务。在MATLAB中,函数定义在单独的文件。文件函数的文件名应该是相同的。 函数操作在自己的工作空间,它也被称为本地工作区,独立的工作区,在 MATLAB 命令提示符访问,这就是所谓的基础工作区的变量。函数可以接受多个输入参数和可能返回多个输出参数 。 MATLAB是MathWorks公司开发的一种编程语言。它最初是一个矩阵的编程语言,使线性代数编程很简单。它可以运行在交互式会话和作为批处理作业。有需要的朋友可以下载看看
- 不要用
fmt.Errorf("invalid ID: %s", id)赋值给包级var—— 这会让变量失去恒定值,errors.Is(err, ErrInvalidID)永远失败 - 不要把带堆栈的错误(如
fmt.Errorf("%w", err))存为全局变量 —— 它们本应是运行时构造的 - 如果错误需携带上下文,改用自定义错误类型,而不是塞进字符串
什么时候直接用 fmt.Errorf 更合适?
绝大多数业务逻辑中的非关键、一次性、带动态信息的错误,直接内联更清晰:
if len(name) == 0 {
return fmt.Errorf("CreateUser: name cannot be empty")
}
if !isValidEmail(email) {
return fmt.Errorf("CreateUser: invalid email format: %q", email)
}
这类错误通常只被日志记录或透传给上层,无需被下游代码 Is 判断,也不构成 API 稳定性承诺。
过度提取会导致包里堆满 ErrXXX 却没人真去判断;反过来,该提取时不提取,又会让错误处理散落在各处、无法统一拦截。边界就在“是否会被 errors.Is 查”和“是否代表一个稳定语义”。









