go-error

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Go Error

Go 错误

Generate typed custom errors for module-level
errs
packages.
为模块级
errs
包生成类型化自定义错误。

When to Use

适用场景

  • Add new custom typed error definitions to a module
  • Extend existing errs.go with new error codes
  • Create validation error helpers with field-level details
  • 为模块添加新的自定义类型错误定义
  • 用新的错误码扩展现有 errs.go 文件
  • 创建携带字段级别详情的校验错误辅助函数

Pattern

规范模式

Place errors in:
internal/modules/<module>/errs/errs.go
Each module error file follows:
  1. package errs
  2. Imports:
    • net/http
    • brickserrs "github.com/cristiano-pacheco/bricks/pkg/errs"
  3. var (...)
    block with exported error variables
  4. Error creation via:
    • brickserrs.New("<MODULE>_<NN>", "<message>", http.<Status>, nil)
  5. Optional helper constructors for validation errors that carry field-level details
错误定义存放路径:
internal/modules/<module>/errs/errs.go
每个模块的错误文件遵循以下规则:
  1. package errs
  2. 导入依赖:
    • net/http
    • brickserrs "github.com/cristiano-pacheco/bricks/pkg/errs"
  3. var (...)
    代码块中定义导出的错误变量
  4. 错误创建方式:
    • brickserrs.New("<MODULE>_<NN>", "<message>", http.<Status>, nil)
  5. 可选:为携带字段级别详情的校验错误添加辅助构造函数

Example Structure

结构示例

go
package errs

import (
	"net/http"

	brickserrs "github.com/cristiano-pacheco/bricks/pkg/errs"
)

var (
	// ErrProfileValidationFailed is returned when profile validation fails.
	ErrProfileValidationFailed = brickserrs.New(
		"PROFILE_01",
		"profile validation failed",
		http.StatusBadRequest,
		nil,
	)
	// ErrProfileNotFound is returned when the profile is not found.
	ErrProfileNotFound = brickserrs.New("PROFILE_02", "profile not found", http.StatusNotFound, nil)
)

// NewProfileValidationError returns a structured validation error with field-level details.
func NewProfileValidationError(details []brickserrs.Detail) *brickserrs.Error {
	return brickserrs.New(
		ErrProfileValidationFailed.Code,
		ErrProfileValidationFailed.Message,
		ErrProfileValidationFailed.Status,
		details,
	)
}
go
package errs

import (
	"net/http"

	brickserrs "github.com/cristiano-pacheco/bricks/pkg/errs"
)

var (
	// ErrProfileValidationFailed is returned when profile validation fails.
	ErrProfileValidationFailed = brickserrs.New(
		"PROFILE_01",
		"profile validation failed",
		http.StatusBadRequest,
		nil,
	)
	// ErrProfileNotFound is returned when the profile is not found.
	ErrProfileNotFound = brickserrs.New("PROFILE_02", "profile not found", http.StatusNotFound, nil)
)

// NewProfileValidationError returns a structured validation error with field-level details.
func NewProfileValidationError(details []brickserrs.Detail) *brickserrs.Error {
	return brickserrs.New(
		ErrProfileValidationFailed.Code,
		ErrProfileValidationFailed.Message,
		ErrProfileValidationFailed.Status,
		details,
	)
}

Generation Steps

生成步骤

  1. Identify error details:
    • Target module (e.g.,
      catalog
      ,
      profile
      ,
      ai
      ,
      export
      )
    • Error variable name (
      ErrProfileNotFound
      )
    • Lowercase message (
      "profile not found"
      )
    • HTTP status (
      http.StatusNotFound
      )
  2. Find the next code:
    • Open
      internal/modules/<module>/errs/errs.go
    • Extract existing codes for that module prefix
    • Allocate the next available sequential code:
      • Single digits are zero-padded:
        CATALOG_01
        ,
        CATALOG_02
        , ...,
        CATALOG_09
      • Double digits are not padded:
        CATALOG_10
        ,
        CATALOG_11
        , ...
    • Keep code uniqueness inside the module
  3. Add the new error:
    • Insert into the module
      var (...)
      block
    • Keep domain-group ordering used by the file
    • Add a short doc comment when comments are already present in the file
  4. Add a helper constructor if needed:
    • When the error is a validation error that carries field-level details, add a
      NewXxxValidationError(details []brickserrs.Detail) *brickserrs.Error
      function
    • Reuse the pre-defined variable's
      .Code
      ,
      .Message
      , and
      .Status
      fields
  5. Validate usage path:
    • Ensure new/updated usecases, validators, handlers, or enum constructors return the new typed error
    • Do not return raw
      errors.New(...)
      from business flows when a typed module error exists
  6. Update translations (mandatory):
    • Every new custom error must add a translation entry in
      locales/en.json
      under the
      "errors"
      key
    • Use the error code as key and a properly capitalized, user-facing sentence as value:
      "PROFILE_02": "Profile not found"
    • If additional locale files exist (for example
      locales/pt_BR.json
      ), add the same key there too
    • Keep translation keys and structure consistent across all locale files
    • Do not merge a new custom error without the corresponding locale updates
  1. 确定错误详情
    • 目标模块(例如
      catalog
      profile
      ai
      export
    • 错误变量名(
      ErrProfileNotFound
    • 小写错误消息(
      "profile not found"
    • HTTP 状态码(
      http.StatusNotFound
  2. 查找下一个可用错误码
    • 打开
      internal/modules/<module>/errs/errs.go
    • 提取该模块前缀下已有的错误码
    • 分配下一个可用的顺序码:
      • 个位数补零:
        CATALOG_01
        CATALOG_02
        、...、
        CATALOG_09
      • 两位数无需补零:
        CATALOG_10
        CATALOG_11
        、...
    • 保证模块内错误码唯一
  3. 添加新错误
    • 插入到模块的
      var (...)
      代码块中
    • 遵循文件已有的领域分组排序规则
    • 如果文件中已有注释,为新错误添加简短的文档注释
  4. 按需添加辅助构造函数
    • 如果错误是携带字段级别详情的校验错误,添加
      NewXxxValidationError(details []brickserrs.Detail) *brickserrs.Error
      函数
    • 复用预定义变量的
      .Code
      .Message
      .Status
      字段
  5. 校验使用路径
    • 确保新增/更新的用例、校验器、处理器或枚举构造函数返回新的类型化错误
    • 当存在对应的模块类型化错误时,业务流程中不要返回原始的
      errors.New(...)
  6. 更新翻译(强制要求)
    • 每个新增的自定义错误都必须在
      locales/en.json
      "errors"
      键下添加翻译条目
    • 使用错误码作为键,首字母大写的面向用户的语句作为值:
      "PROFILE_02": "Profile not found"
    • 如果存在其他语言的本地化文件(例如
      locales/pt_BR.json
      ),也要在其中添加相同的键
    • 保持所有本地化文件中的翻译键和结构一致
    • 没有完成对应本地化更新的自定义错误不要合并

Naming Conventions

命名规范

  • Variable:
    Err
    + clear domain phrase in PascalCase
    • Example:
      ErrProfileNotFound
      ,
      ErrAIGenerationFailed
  • Code:
    <MODULE>_<NN>
    • CATALOG_09
      ,
      EXPORT_15
      ,
      AI_07
    • Always at least 2 digits; single digits are zero-padded
  • Message:
    • All lowercase in
      brickserrs.New()
      — the locale file (
      locales/en.json
      ) provides the user-facing capitalized form
    • Short and specific, no trailing punctuation
    • Examples:
      "profile not found"
      ,
      "invalid prompt type"
      ,
      "ai provider unavailable"
  • HTTP status:
    • Validation errors:
      http.StatusBadRequest
    • Auth failures:
      http.StatusUnauthorized
      /
      http.StatusForbidden
    • Missing resources:
      http.StatusNotFound
    • Conflicts:
      http.StatusConflict
    • Rate limit:
      http.StatusTooManyRequests
    • Upstream/AI failures:
      http.StatusBadGateway
    • Capacity/availability:
      http.StatusServiceUnavailable
    • Infra/internal failures:
      http.StatusInternalServerError
  • 变量名
    Err
    + 帕斯卡命名的清晰领域短语
    • 示例:
      ErrProfileNotFound
      ErrAIGenerationFailed
  • 错误码
    <MODULE>_<NN>
    • 示例:
      CATALOG_09
      EXPORT_15
      AI_07
    • 始终至少2位数字;个位数补零
  • 错误消息
    • brickserrs.New()
      中的消息全部小写——本地化文件(
      locales/en.json
      )提供面向用户的首字母大写格式
    • 简短明确,末尾无标点
    • 示例:
      "profile not found"
      "invalid prompt type"
      "ai provider unavailable"
  • HTTP 状态码
    • 校验错误:
      http.StatusBadRequest
    • 认证失败:
      http.StatusUnauthorized
      /
      http.StatusForbidden
    • 资源不存在:
      http.StatusNotFound
    • 资源冲突:
      http.StatusConflict
    • 限流:
      http.StatusTooManyRequests
    • 上游/AI 服务故障:
      http.StatusBadGateway
    • 容量/可用性问题:
      http.StatusServiceUnavailable
    • 基础设施/内部故障:
      http.StatusInternalServerError

Implementation Checklist

实现检查清单

  • Open target
    internal/modules/<module>/errs/errs.go
  • Compute next unique module code (zero-padded 2-digit format)
  • Add exported
    Err...
    variable with
    brickserrs.New(...)
  • Use all-lowercase message string
  • Match existing domain-group ordering style
  • Ensure message and status align with domain behavior
  • Add
    NewXxxValidationError(details []brickserrs.Detail)
    helper if it is a validation error
  • Replace raw error returns in calling code with typed
    errs.Err...
    where applicable
  • Add translation for the new error in
    locales/en.json
    under
    "errors"
    with proper sentence-case value
  • Add the same translation key in every other existing locale file (e.g.,
    locales/pt_BR.json
    )
  • Run
    make lint
    to catch style and static analysis issues
  • Run
    make nilaway
    to ensure no nil pointer dereferences are introduced
  • 打开目标路径的
    internal/modules/<module>/errs/errs.go
  • 计算下一个唯一的模块错误码(补零的2位格式)
  • 通过
    brickserrs.New(...)
    添加导出的
    Err...
    变量
  • 使用全小写的消息字符串
  • 符合已有的领域分组排序风格
  • 确保消息和状态码与领域行为匹配
  • 如果是校验错误,添加
    NewXxxValidationError(details []brickserrs.Detail)
    辅助函数
  • 在适用的调用代码中,将原始错误返回替换为类型化的
    errs.Err...
  • locales/en.json
    "errors"
    下添加新错误的翻译,值使用正确的句首大写格式
  • 在所有其他已有的本地化文件(例如
    locales/pt_BR.json
    )中添加相同的翻译键
  • 运行
    make lint
    检查风格和静态分析问题
  • 运行
    make nilaway
    确保没有引入空指针引用问题

Usage Pattern

使用示例

go
if input.Phone == "" {
	return errs.ErrPhoneNumberRequired
}

if profile == nil {
	return errs.ErrProfileNotFound
}
go
if input.Phone == "" {
	return errs.ErrPhoneNumberRequired
}

if profile == nil {
	return errs.ErrProfileNotFound
}

Critical Rules

核心规则

  • No standalone functions: When a file contains a struct with methods, do not add standalone functions. Use private methods on the struct instead.
  • Do not create a new error package; use module-local
    internal/modules/<module>/errs
  • Do not duplicate codes within the same module
  • Do not return persistence or infrastructure-specific raw errors to transport when a typed domain error exists
  • Keep error messages stable once exposed, unless migration/compatibility impact is accepted
  • Every new custom error requires locale entries in
    locales/en.json
    and all other existing locale files
  • Messages in
    brickserrs.New()
    are always lowercase; user-facing capitalization lives in the locale file
  • 禁止独立函数:如果文件中包含带有方法的结构体,不要添加独立函数,改用结构体的私有方法
  • 不要创建新的错误包,使用模块本地的
    internal/modules/<module>/errs
  • 同一模块内不要重复定义错误码
  • 当存在对应的领域类型化错误时,不要将持久层或基础设施相关的原始错误返回给传输层
  • 错误消息一旦对外暴露后要保持稳定,除非接受迁移/兼容性影响
  • 每个新增的自定义错误都需要在
    locales/en.json
    和所有其他已有的本地化文件中添加本地化条目
  • brickserrs.New()
    中的消息始终使用小写;面向用户的大写格式存放在本地化文件中