参数绑定
Fox 自动将来自各种来源的请求参数绑定到您的处理函数参数。
Fox 可以从以下来源绑定参数:
- URI 路径参数 -
/user/:id(使用uri标签) - 查询字符串 -
?name=value(使用query或form标签) - JSON 请求体 -
Content-Type: application/json(使用json标签) - 表单数据 -
Content-Type: application/x-www-form-urlencoded(使用form标签) - 请求头 - 自定义 HTTP 请求头 (使用
header标签)
URI 参数
Section titled “URI 参数”type UserRequest struct { ID int `uri:"id" binding:"required"`}
r.GET("/user/:id", func(req *UserRequest) (*User, error) { return getUserByID(req.ID)})Fox 支持使用 form 和 query 标签来绑定 URL 查询参数:
type SearchRequest struct { Query string `query:"q" binding:"required"` // 使用 query 标签 Page int `query:"page"` Size int `query:"size"`}
// 或者使用 form 标签(两者效果相同)type SearchRequest struct { Query string `form:"q" binding:"required"` // 使用 form 标签 Page int `form:"page"` Size int `form:"size"`}
r.GET("/search", func(req *SearchRequest) ([]Result, error) { return search(req.Query, req.Page, req.Size)})JSON 请求体
Section titled “JSON 请求体”type CreateUserRequest struct { Name string `json:"name" binding:"required"` Email string `json:"email" binding:"required,email"` Age int `json:"age" binding:"gte=0,lte=130"` Password string `json:"password" binding:"required,min=8"`}
r.POST("/users", func(req *CreateUserRequest) (*User, error) { return createUser(req)})在单个结构体中从多个来源绑定:
type UpdateUserRequest struct { ID int `uri:"id" binding:"required"` // 从路径 Name string `json:"name" binding:"required"` // 从 JSON 请求体 AuthUser string `header:"X-Auth-User" binding:"required"` // 从请求头}
r.PUT("/user/:id", func(req *UpdateUserRequest) error { return updateUser(req.ID, req.Name, req.AuthUser)})Fox 使用 validator 库进行验证:
type UserInput struct { // 必填字段 Name string `json:"name" binding:"required"`
// 邮箱验证 Email string `json:"email" binding:"required,email"`
// 长度约束 Username string `json:"username" binding:"required,min=3,max=20"`
// 数值范围 Age int `json:"age" binding:"gte=0,lte=130"`
// URL 验证 Website string `json:"website" binding:"omitempty,url"`
// 枚举验证 Role string `json:"role" binding:"required,oneof=admin user guest"`
// 自定义正则 Phone string `json:"phone" binding:"required,e164"` // E.164 电话格式}type Address struct { Street string `json:"street" binding:"required"` City string `json:"city" binding:"required"` Country string `json:"country" binding:"required,iso3166_1_alpha2"`}
type CreateUserRequest struct { Name string `json:"name" binding:"required"` Email string `json:"email" binding:"required,email"` Address Address `json:"address" binding:"required"`}type BatchRequest struct { IDs []int `json:"ids" binding:"required,min=1,max=100,dive,gte=1"` Emails []string `json:"emails" binding:"required,dive,email"`}dive 标签验证切片中的每个元素。
使用 omitempty 标记可选字段:
type FilterRequest struct { Name string `form:"name"` // 可选,无验证 Category string `form:"category" binding:"omitempty,oneof=books electronics"` MinPrice *int `form:"min_price" binding:"omitempty,gte=0"`}在结构体初始化时设置默认值:
type PaginationRequest struct { Page int `form:"page"` Size int `form:"size"`}
r.GET("/items", func(req *PaginationRequest) ([]Item, error) { // 如果未提供则设置默认值 if req.Page == 0 { req.Page = 1 } if req.Size == 0 { req.Size = 20 }
return getItems(req.Page, req.Size)})当绑定或验证失败时,Fox 自动返回带有详细信息的 400 错误:
{ "error": "Key: 'CreateUserRequest.Email' Error:Field validation for 'Email' failed on the 'email' tag"}自定义错误消息
Section titled “自定义错误消息”实现自定义错误处理:
r.SetErrorHandler(func(c *gin.Context, err error) { if validationErr, ok := err.(validator.ValidationErrors); ok { errors := make(map[string]string) for _, e := range validationErr { errors[e.Field()] = fmt.Sprintf("'%s' 验证失败", e.Tag()) } c.JSON(400, gin.H{"errors": errors}) return } c.JSON(500, gin.H{"error": err.Error()})})Fox 自动将字符串参数转换为目标类型:
type Request struct { ID int `uri:"id"` // "123" -> 123 Active bool `form:"active"` // "true" -> true Price float64 `form:"price"` // "19.99" -> 19.99 Date time.Time `form:"date" time_format:"2006-01-02"`}- 始终验证必填字段 - 对必需参数使用
binding:"required" - 使用特定验证标签 - 明确约束条件(
min、max、email等) - 记录结构体 - 添加注释说明字段和验证规则
- 对可选字段使用指针 - 区分”未提供”和”零值”
- 保持结构体专注 - 为不同操作创建独立的请求结构体