Golang实现带UI反馈的错误系统_Web端异常提示设计

3次阅读

应统一用结构化 AppError 包装错误,含 code、message、field 字段,禁用 errors.New;http handler 返回 json 对象而非字符串;前端按 code 分支处理,不依赖 HTTP 状态码。

Golang实现带UI反馈的错误系统_Web端异常提示设计

go 后端怎么把错误传给前端显示

后端不能直接把 error 原样塞进 JSON 响应里发给前端——没结构、没分类、可能带敏感路径或调试信息。得先统一包装成前端能识别的格式,比如带 codemessagefield 的对象。

常见错误现象:前端收到 {"error":"invalid email format"},但 ui 不知道该弹框还是内联提示;或者后端 panic 日志被当普通错误返回,暴露了 /var/www/app/main.go:123 这种路径。

  • 所有业务错误必须走自定义错误类型,比如 AppError,实现 Error() 方法且携带 Code()Message()
  • HTTP handler 中用 json.NewEncoder(w).Encode() 返回结构体,不是 fmt.Fprintf 拼字符串
  • 全局 panic 恢复中间件里,对非 AppError 类型错误,一律返回通用码如 "INTERNAL_ERROR",message 固定为 "Something went wrong"

前端怎么区分网络错误、校验失败、权限不足

靠后端返回的 code 字段,不是靠 HTTP 状态码猜。400 不一定代表表单错,500 也不一定真崩了——很多网关会把超时也转成 500。

使用场景:用户提交邮箱,后端返回 {"code":"VALIDATION_FAILED","message":"Email is invalid","field":"email"},前端就只在邮箱输入框下方显示红字;如果是 {"code":"FORBIDDEN"},就跳登录页。

立即学习go语言免费学习笔记(深入)”;

  • 约定好几类标准 code:VALIDATION_FAILEDNOT_FOUNDFORBIDDENRATE_LIMITED,全部大写+下划线
  • field 字段只在 VALIDATION_FAILED 时存在,值对应前端表单控件的 nameid
  • 避免用 HTTP 状态码做业务分支,比如不写 if status === 403 跳登录,而应检查 res.code === "FORBIDDEN"

为什么不能在 Go 里用 errors.New("xxx") 直接返回

因为它没结构、没上下文、没法加字段,前端拿不到 code,日志里也看不出是哪个接口、哪个参数出的问题。

性能影响不大,但可维护性差:加个新错误要改三处——handler 里写字符串、前端加 case、文档补说明。

  • 用结构体定义错误:type AppError Struct { Code String; Message string; Field string; }
  • 提供构造函数NewValidationError(field, msg string) *AppError,内部固定设 Code: "VALIDATION_FAILED"
  • 日志记录时,用 zap.Error(err) 打印时会自动展开结构体字段,不用手动拼 err.Code + err.Message

UI 层怎么避免重复提示或提示消失太快

不是后端问题,但和错误结构强相关。如果后端每次返回都带完整 message,前端又没做防抖或合并,用户点两次按钮就会弹两个 Toast。

容易踩的坑:把 loading 状态和错误状态耦合,比如请求中禁用按钮,但错误后没恢复按钮状态,用户以为卡住了。

  • 前端收到响应后,先清空上一次的 field 对应错误,再按新 field 设置;全局错误(无 field)单独存一个 slot
  • Toast 提示加唯一 key,比如用 code + timestamp,防止相同错误连发被重复渲染
  • 表单提交后,按钮置灰逻辑和错误处理解耦:按钮状态由 isSubmitting 控制,错误展示由 errors 对象控制

真正难的是错误边界——比如上传文件时网络中断,后端根本没收到请求,这时候错误不在 AppError 体系里,得靠前端 fetch 的 reject 分支兜底,而这个分支的 message 格式又要和后端保持一致。这事得前后端一起对齐,光后端做得再规范也没用。

text=ZqhQzanResources