答案:Go语言中通过定义统一的错误响应结构体和错误码常量,结合工厂函数与中间件,实现REST API的标准化错误返回,提升前后端协作效率与系统可维护性。

在Go语言构建的REST API中,统一的错误返回格式有助于前端或API调用者快速理解错误原因并做相应处理。以下是一个常见的错误返回规范示例,包含结构设计、HTTP状态码使用和实际代码实现。
统一错误响应结构
定义一个通用的错误响应体结构,便于前后端达成一致。
{
"error": {
"code": "invalid_request",
"message": "请求参数缺失或格式错误",
"details": "field 'email' is required"
}
}
说明:
-
code:机器可读的错误码,如
invalid_request
、not_found
- message:人类可读的错误信息(可本地化)
- details:可选字段,用于补充上下文,如校验失败字段
定义错误类型和构造函数
在Go中可以通过结构体和工厂函数来封装错误响应。
立即学习“go语言免费学习笔记(深入)”;
type ErrorResponse struct {
Error struct {
Code string `json:"code"`
Message string `json:"message"`
Details string `json:"details,omitempty"`
} `json:"error"`
}
func NewErrorResponse(code, message, details string) *ErrorResponse {
resp := ErrorResponse{}
resp.Error.Code = code
resp.Error.Message = message
resp.Error.Details = details
return &resp
}
常见错误码可定义为常量:
const (
ErrInvalidRequest = "invalid_request"
ErrUnauthorized = "unauthorized"
ErrNotFound = "not_found"
ErrInternal = "internal_error"
)
在HTTP Handler中使用示例
结合
net/http返回标准错误响应。
func GetUserHandler(w http.ResponseWriter, r *http.Request) {
id := r.PathValue("id")
if id == "" {
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusBadRequest)
resp := NewErrorResponse(
ErrInvalidRequest,
"用户ID不能为空",
"path param 'id' is missing",
)
json.NewEncoder(w).Encode(resp)
return
}
// 模拟查询用户
user, err := db.GetUser(id)
if err != nil {
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusInternalServerError)
resp := NewErrorResponse(ErrInternal, "服务器内部错误", err.Error())
json.NewEncoder(w).Encode(resp)
return
}
if user == nil {
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusNotFound)
resp := NewErrorResponse(ErrNotFound, "用户不存在", "user with id "+id+" not found")
json.NewEncoder(w).Encode(resp)
return
}
json.NewEncoder(w).Encode(user)
}
进阶:中间件统一错误处理
可以结合自定义错误类型和中间件,实现更优雅的错误处理。
type AppError struct {
Code string
Message string
Details string
Status int
}
func (e *AppError) Error() string {
return e.Message
}
func ErrorMiddleware(next http.HandlerFunc) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
defer func() {
if err := recover(); err != nil {
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusInternalServerError)
resp := NewErrorResponse(ErrInternal, "系统错误", fmt.Sprintf("%v", err))
json.NewEncoder(w).Encode(resp)
}
}()
next(w, r)
}
}
这样可以在业务逻辑中直接返回或抛出自定义错误,在中间件中统一处理。
基本上就这些。保持错误格式一致、语义清晰,能显著提升API的可用性和维护性。










