Go中实现统一错误格式返回需封装结构化错误对象,定义含Code、Message、StatusCode等字段的AppError结构体,实现Error()方法,配合快捷构造函数、预定义错误变量、中间件统一拦截,确保前端可依据code分支处理、status code控制行为,后端便于日志监控。
在 Go 中实现统一错误格式返回,核心是避免直接用 errors.New 或 fmt.Errorf 返回裸错误,而是封装成结构化、可序列化、带上下文和状态码的错误对象,并在 HTTP 层统一拦截、标准化响应。
创建一个符合业务需要的错误类型,通常包含错误码、消息、HTTP 状态码、可选的详情字段(如请求 ID、时间戳):
error 接口的 Error() 方法,供日志或调试使用Code, Message, StatusCode),方便中间件读取type AppError struct {
Code int `json:"code"`
Message string `json:"message"`
StatusCode int `json:"status_code"`
RequestID string `json:"request_id,omitempty"`
}
func (e *AppError) Error() string {
return fmt.Sprintf("code=%d message=%s", e.Code, e.Message)
}
// 快捷构造函数
func NewAppError(code int, msg string, statusCode int) *AppError {
return &AppError{
Code: code,
Message: msg,
StatusCode: statusCode,
}
}
按业务场景预定义错误变量或工厂函数,避免硬编码字符串和状态码:
ErrInvalidParam = 1001)BadRequest, NotFound, InternalError)Wrap 包装底层 error,但保持结构体主体不变)var (
ErrInvalidParam = NewAppError(1001, "invalid parameter", http.StatusBadRequest)
ErrNotFound = NewAppError(1004, "resource not found", http.StatusNotFound)
)
func WrapAppError(err error, appErr *AppError) *AppError {
if err == nil {
return appErr
}
return &AppError{
Code: appErr.Code,
Message: fmt.Sprintf
("%s: %v", appErr.Message, err),
StatusCode: appErr.StatusCode,
RequestID: appErr.RequestID,
}
}
不 panic,不裸 return error,而是显式构造并提前返回结构化错误响应:
*AppError 并写入响应func GetUser(w http.ResponseWriter, r *http.Request) {
id := r.URL.Query().Get("id")
if id == "" {
renderError(w, ErrInvalidParam)
return
}
user, err := userService.Get(id)
if err != nil {
renderError(w, ErrNotFound)
return
}
renderJSON(w, http.StatusOK, user)
}
对未被 handler 显式处理的 panic 或未预期 error,用 recover + middleware 统一封装:
500 Internal Server Error
*AppError,直接渲染;否则兜底转为通用服务错误application/json,并设置正确 status codefunc ErrorHandler(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
defer func() {
if r := recover(); r != nil {
err := NewAppError(5000, "internal server error", http.StatusInternalServerError)
renderError(w, err)
}
}()
next.ServeHTTP(w, r)
})
}
func renderError(w http.ResponseWriter, err *AppError) {
w.Header().Set("Content-Type", "application/json; charset=utf-8")
w.WriteHeader(err.StatusCode)
json.NewEncoder(w).Encode(map[string]interface{}{
"success": false,
"error": err,
})
}
不复杂但容易忽略的是:统一错误格式不只是“长得一样”,关键是让前端能靠 code 做逻辑分支、靠 status code 控制重试或跳转、靠 message 做用户提示,同时后端日志和监控能按 code 聚类分析。结构体设计要兼顾可读性、可扩展性和安全性(比如不把数据库错误堆栈直接透出)。
# js
# 前端
# json
# go
# golang
# 编码
# app
# usb
# 后端
# 栈
# 状态码
# 日志监控
# 中间件
# 常量
# 封装
# 构造函数
# Error
# 字符串
# 结构体
# 接口
# 堆
# internal
# 对象
# 数据库
# http
# 的是
# 结构化
# 链式
# 序列化
# 错误码
# 并在
# 长得
# 可选
# 跳转
相关文章:
建站之星logo尺寸如何设置最合适?
如何在云指建站中生成FTP站点?
如何通过IIS搭建网站并配置访问权限?
如何在宝塔面板创建新站点?
浅谈Javascript中的Label语句
建站之星代理平台如何选择最佳方案?
如何通过WDCP绑定主域名及创建子域名站点?
网站制作的软件有哪些,制作微信公众号除了秀米还有哪些比较好用的平台?
学校建站服务器如何选型才能满足性能需求?
已有域名和空间,如何快速搭建网站?
如何在IIS中配置站点IP、端口及主机头?
一键网站制作软件,义乌购一件代发流程?
建站为何优先选择香港服务器?
建站之星与建站宝盒如何选择最佳方案?
如何获取开源自助建站系统免费下载链接?
网站制作需要会哪些技术,建立一个网站要花费多少?
免费制作统计图的网站有哪些,如何看待现如今年轻人买房难的情况?
大型企业网站制作流程,做网站需要注册公司吗?
建站主机核心功能解析:服务器选择与网站搭建流程指南
如何通过二级域名建站提升品牌影响力?
小自动建站系统:AI智能生成+拖拽模板,多端适配一键搭建
如何在IIS管理器中快速创建并配置网站?
已有域名如何免费搭建网站?
建站VPS选购需注意哪些关键参数?
如何快速搭建个人网站并优化SEO?
建站之星安装失败:服务器环境不兼容?
php条件判断怎么写_ifelse和switchcase的使用区别【对比】
*服务器网站为何频现安全漏洞?
如何在IIS7中新建站点?详细步骤解析
如何通过宝塔面板实现本地网站访问?
宝塔建站教程:一键部署配置流程与SEO优化实战指南
企业微网站怎么做,公司网站和公众号有什么区别?
SQL查询语句优化的实用方法总结
韩国代理服务器如何选?解析IP设置技巧与跨境访问优化指南
如何打造高效商业网站?建站目的决定转化率
公司网站建设制作费用,想建设一个属于自己的企业网站,该如何去做?
广平建站公司哪家专业可靠?如何选择?
如何在搬瓦工VPS快速搭建网站?
建站之星代理商如何保障技术支持与售后服务?
如何通过FTP服务器快速搭建网站?
家庭建站与云服务器建站,如何选择更优?
高防服务器租用指南:配置选择与快速部署攻略
建站之星Pro快速搭建教程:模板选择与功能配置指南
上海网站制作网页,上海本地的生活网站有哪些?最好包括生活的各个方面的?
如何在云主机上快速搭建网站?
宝塔面板如何快速创建新站点?
如何在VPS电脑上快速搭建网站?
网站网页制作电话怎么打,怎样安装和使用钉钉软件免费打电话?
建站之星如何一键生成手机站?
内网网站制作软件,内网的网站如何发布到外网?
*请认真填写需求信息,我们会在24小时内与您取得联系。