错误处理与状态码
良好的错误处理能提升 API 的可用性和可维护性。
HTTP 状态码
常用状态码
| 状态码 | 含义 | 使用场景 |
|---|---|---|
| 200 | OK | 请求成功 |
| 201 | Created | 资源创建成功 |
| 400 | Bad Request | 参数错误 |
| 401 | Unauthorized | 未认证 |
| 403 | Forbidden | 无权限 |
| 404 | Not Found | 资源不存在 |
| 500 | Internal Server Error | 服务器错误 |
使用常量
Go
import "net/http"
r.GET("/success", func(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{"message": "success"})
})
r.GET("/notfound", func(c *gin.Context) {
c.JSON(http.StatusNotFound, gin.H{"error": "resource not found"})
})
统一错误响应
定义错误结构
Go
type ErrorResponse struct {
Code int `json:"code"`
Message string `json:"message"`
}
func SendError(c *gin.Context, status int, message string) {
c.JSON(status, ErrorResponse{
Code: status,
Message: message,
})
}
// 使用
r.GET("/user/:id", func(c *gin.Context) {
id := c.Param("id")
if id == "" {
SendError(c, http.StatusBadRequest, "缺少用户ID")
return
}
c.JSON(http.StatusOK, gin.H{"id": id})
})
自定义错误处理
全局错误处理
Go
func ErrorHandler() gin.HandlerFunc {
return func(c *gin.Context) {
defer func() {
if err := recover(); err != nil {
c.JSON(http.StatusInternalServerError, gin.H{
"code": 500,
"message": "服务器内部错误",
})
}
}()
c.Next()
}
}
func main() {
r := gin.New()
r.Use(ErrorHandler())
// ...
}
绑定错误处理
Go
type User struct {
Name string `json:"name" binding:"required"`
Age int `json:"age" binding:"gte=0,lte=150"`
}
r.POST("/user", func(c *gin.Context) {
var user User
if err := c.ShouldBindJSON(&user); err != nil {
c.JSON(http.StatusBadRequest, gin.H{
"code": 400,
"message": "参数校验失败: " + err.Error(),
})
return
}
c.JSON(http.StatusOK, gin.H{"name": user.Name})
})
状态码使用建议
Go
// 创建资源成功
r.POST("/users", func(c *gin.Context) {
// 创建用户逻辑
c.JSON(http.StatusCreated, gin.H{"id": 1})
})
// 无权限访问
r.GET("/admin", func(c *gin.Context) {
c.JSON(http.StatusForbidden, gin.H{
"error": "无权访问",
})
})
业务错误和 HTTP 错误要区分清楚,HTTP 状态码反映协议层面,响应体 code 反映业务层面。
要点总结
- 使用
net/http常量定义状态码,代码更清晰 - 统一错误响应格式,便于前端处理
- 全局错误处理通过中间件实现
- 业务状态码和 HTTP 状态码要区分使用
📝 发现内容有误?点击此处直接编辑