该用%w,不是%v,因为%w支持错误链、errors.Is/As判断,而%v丢失原始类型和堆栈;%w必须置于格式串末尾且仅接一个error。
fmt.Errorf 里该用 %w 还是 %v?
用
,不是
,这是 Go 错误链能否工作的分水岭。用错就等于主动切断调试线索。
会把原始错误嵌入新错误中,支持
和
判断——比如你能精准识别出是不是
,而不是靠字符串匹配
只是把错误转成字符串拼进去,原始类型和堆栈全丢,
永远返回
必须放在格式化字符串的末尾,且只能接一个
类型值;写成
是非法语法
常见错误现象:日志里看到 “failed to save user: &{…}”,但上层无法用
判断类型,最终所有错误都 fallback 到 500 ——其实本该是 404。
自定义 error 结构体时,Error() 方法怎么写?
方法只负责返回面向调用方的可读提示,不是调试日志,也不是错误分类器。
必须小写开头、不加句号,例如
,不是
或
不能包含路径、密码、token、用户 ID 等敏感信息;调试用的字段(如
、
)要单独存,绝不塞进
返回值
如果需要包装底层错误,必须实现
并返回它;漏掉
,
包装和
都会失效
示例中常看到
忘记
,导致
总是失败,最后只能靠字符串判断,一换语言或翻译就崩。
立即学习
“
go语言免费学习笔记(深入)
”;
go语言参考手册 中文CHM版
Go 是一个开源的编程语言,它能让构造简单、可靠且高效的软件变得容易。本文给大家带来Go参考手册,需要的可以来下载! Go是从2007年末由Robert Griesemer, Rob Pike, Ken Thompson主持开发,后来还加入了Ian Lance Taylor, Russ Cox等人,并最终于2009年11月开源,在2012年早些时候发布了Go 1稳定版本。现在Go的开发已经是完全开放的,并且拥有一个活跃的社区。 Go 语言特色 简洁、快速、安全 并行、有趣、开源 内存管理、v数组安全、编译
下载
HTTP 接口返回错误时,message 和 details 怎么分?
响应给前端的
和记录到日志里的上下文,必须物理隔离——它们服务的对象、用途、安全要求完全不同。
是给用户的,要简短、中性、无技术细节,例如
,不是
字段只用于内部日志或调试接口,生产环境应为空或脱敏;它不该出现在 JSON 响应里,除非明确开启 debug 模式
状态码不能靠
匹配——这种写法在加个前缀日志、换种错误包装后立刻失效
正确做法是让错误实现
接口,由统一响应函数读取,而不是每个 handler 自己 if-else 判字符串。
团队协作中,错误文案风格为什么必须统一?
不是为了好看,而是为了让
能搜、监控能聚、新人能懂、CI 能校验。
动词开头(
)、小写、无句号,是硬约束——否则日志系统按正则聚合时,
和
就算作两个错误类型
同一类错误在 CLI、HTTP、gRPC 中的提示语气可以不同,但核心动词和名词必须一致,比如都用
而不是有时用
、有时用
禁止在
里写 “请联系管理员” 或 “请重试”——那是业务响应逻辑,不是错误本身;错误只说“发生了什么”,不说“该怎么办”
最容易被忽略的一点:错误消息里混用中文和英文变量名(比如
),会导致国际化时模板难维护、机器翻译出错、甚至 JSON 序列化失败。统一用英文占位符,靠 message key + i18n 模板解耦才是正路。
%w%v%werrors.Iserrors.Asos.ErrNotExist%verrors.Is(err, os.ErrNotExist)false%werrorfmt.Errorf("read %s: %w, retrying: %w", f, err1, err2)errors.IsError()"invalid email format""Invalid email format.""Email validation failed: xxx"TraceIDSQLError()Unwrap() errorUnwrap%werrors.UnwrapValidationErrorUnwrap()errors.As(err, &e)messagemessage"资源未找到""user_id=123 not found in pg.users (query took 82ms)"detailsstrings.Contains(err.Error(), "not found")StatusCode() intgrep"failed to connect""Failed to connect""failed to connect."parsedecodereadError()"参数 name 无效"