Go语言通过返回error值处理错误,第三方库严格遵循不忽略、不泛化、不隐藏、要分类、可恢复则重试、不可恢复则透传或转换的原则;必须检查err是否为nil,优先使用errors.Is或类型断言判断特定错误(如sql.ErrNoRows、context.DeadlineExceeded),避免字符串匹配;推荐用fmt.Errorf("%w")包装错误以保留上下文,但禁止重复包装;多错误可用errors.Join合并;应统一映射为业务错误码并结构化日志记录,避免泄露敏感信息。
Go 语言本身没有异常(exception)机制,而是通过返回 error 值显式表达错误,第三方库也严格遵循这一约定。处理第三方库错误的核心原则是:**不忽略、不泛化、不隐藏、要分类、可恢复则重试,不可恢复则透传或转换为业务语义明确的错误**。
这是最基础也最容易被忽略的一环。几乎所有 Go 第三方库(如 github.com/go-sql-driver/mysql、gopkg.in/yaml.v3、github.com/aws/aws-sdk-go)都按标准返回 (result, error)。若直接忽略 err,会导致静默失败。
nil, nil(例如某些缓存 Get 操作未命中),需结合文档确认语义很多库提供可识别的错误变量或类型(如 os.IsNotExist、sql.ErrNoRows),应优先使用类型断言或专用判断函数,而非 strings.Contains(err.Error(), "timeout")。
minio.BucketNotFound)可用类型断言:if _, ok := err.(minio.BucketNotFound); ok { ... }
使用 fmt.Errorf("xxx: %w", err) 或 errors.Join 添加调用上下文,便于定位问题源头;但不要层层套娃(如 "failed to save user: failed to insert into db: pq: duplicate key...")。
立即学习“go语言免费学习笔记(深入)”;
pload failed: %s", err.Error())(丢失原始 error 链)go build -gcflags="-l" -ldflags="-s -w" 不影响 error 包装链的调试能力面向外部 API 或微服务时,建议将第三方库错误映射为内部错误码(如 ErrStorageUnavailable = 5001),并在日志中结构化记录原始错误类型和关键字段。
errors.Unwrap 或自定义 Error() 方法控制输出基本上就这些。Go 的错误处理不复杂,但容易因“省事”而埋下隐患。坚持显式检查、精准判断、适度包装、统一归因,第三方库错误就能从麻烦变成清晰的系统信号。