参数结构
VEF Framework 使用结构体定义 API 的请求参数。不同类型的操作需要不同的参数结构。
参数类型
| 类型 | 用途 | 示例 |
|---|---|---|
| 搜索参数 | 查询条件 | UserSearch |
| 创建参数 | 创建记录 | UserCreateParams |
| 更新参数 | 更新记录 | UserUpdateParams |
| 通用参数 | 创建和更新共用 | UserParams |
搜索参数
搜索参数用于定义查询条件,配合 search 标签自动构建 SQL 条件。
go
package payloads
import "github.com/ilxqx/vef-framework-go/api"
// UserSearch defines search parameters for user queries
type UserSearch struct {
api.P // Embed api.P for pagination support
// Search by username (contains)
Username string `json:"username" search:"contains"`
// Search by email (exact match)
Email string `json:"email" search:"eq"`
// Search by status (in list)
Status []string `json:"status" search:"in"`
// Search by age range
MinAge int `json:"minAge" search:"gte,column:age"`
MaxAge int `json:"maxAge" search:"lte,column:age"`
// Search by active status
IsActive *bool `json:"isActive" search:"eq"`
// Search by creation date range
CreatedAtStart string `json:"createdAtStart" search:"gte,column:created_at"`
CreatedAtEnd string `json:"createdAtEnd" search:"lte,column:created_at"`
}api.P 嵌入
所有搜索参数应嵌入 api.P,它提供分页支持:
go
type P struct {
Page int `json:"page"` // Page number (1-based)
PageSize int `json:"pageSize"` // Items per page
}创建/更新参数
通用参数(创建和更新共用)
当创建和更新使用相同的字段时:
go
// UserParams is used for both create and update operations
type UserParams struct {
api.P
Id string `json:"id"` // Required for update, ignored for create
Username string `json:"username" validate:"required,alphanum,min=3,max=32" label:"用户名"`
Email string `json:"email" validate:"required,email" label:"邮箱"`
DisplayName string `json:"displayName" validate:"max=64" label:"显示名称"`
IsActive bool `json:"isActive"`
}分离的创建和更新参数
当创建和更新有不同的验证规则时,使用结构体嵌入共享字段:
go
// UserBaseParams contains shared fields
type UserBaseParams struct {
api.P
Username string `json:"username" validate:"required,alphanum,min=3,max=32" label:"用户名"`
Email string `json:"email" validate:"required,email" label:"邮箱"`
DisplayName null.String `json:"displayName" validate:"omitempty,max=64" label:"显示名称"`
IsActive bool `json:"isActive"`
}
// UserCreateParams requires password for creation
type UserCreateParams struct {
UserBaseParams `json:",inline"`
Password string `json:"password" validate:"required,min=6,max=32" label:"密码"`
PasswordConfirm string `json:"passwordConfirm" validate:"required,eqfield=Password" label:"确认密码"`
}
// UserUpdateParams has optional password for update
type UserUpdateParams struct {
UserBaseParams `json:",inline"`
Id string `json:"id"`
Password null.String `json:"password" validate:"omitempty,min=6,max=32" label:"密码"`
PasswordConfirm null.String `json:"passwordConfirm" validate:"omitempty,eqfield=Password" label:"确认密码"`
}在资源中使用分离的参数
go
type UserResource struct {
api.Resource
apis.FindPageApi[models.User, payloads.UserSearch]
apis.CreateApi[models.User, payloads.UserCreateParams] // Use create params
apis.UpdateApi[models.User, payloads.UserUpdateParams] // Use update params
apis.DeleteApi[models.User]
}验证标签
使用 validate 标签定义验证规则:
go
type UserParams struct {
api.P
// Required field
Username string `json:"username" validate:"required" label:"用户名"`
// Required with format validation
Email string `json:"email" validate:"required,email" label:"邮箱"`
// Optional with validation when provided
Phone string `json:"phone" validate:"omitempty,len=11,numeric" label:"手机号"`
// Length constraints
Password string `json:"password" validate:"required,min=6,max=32" label:"密码"`
// Enum validation
Status string `json:"status" validate:"required,oneof=active inactive pending" label:"状态"`
// Cross-field validation
PasswordConfirm string `json:"passwordConfirm" validate:"required,eqfield=Password" label:"确认密码"`
// Numeric range
Age int `json:"age" validate:"omitempty,min=0,max=150" label:"年龄"`
}常用验证规则
| 规则 | 说明 | 示例 |
|---|---|---|
required | 必填 | validate:"required" |
omitempty | 可选(空值跳过验证) | validate:"omitempty,email" |
min | 最小值/长度 | validate:"min=6" |
max | 最大值/长度 | validate:"max=32" |
len | 精确长度 | validate:"len=11" |
email | 邮箱格式 | validate:"email" |
url | URL 格式 | validate:"url" |
uuid | UUID 格式 | validate:"uuid" |
alpha | 仅字母 | validate:"alpha" |
alphanum | 字母数字 | validate:"alphanum" |
numeric | 数字字符串 | validate:"numeric" |
oneof | 枚举值 | validate:"oneof=a b c" |
eqfield | 等于另一字段 | validate:"eqfield=Password" |
label 标签
label 标签用于在验证错误消息中显示友好的字段名称:
go
type Params struct {
Username string `json:"username" validate:"required" label:"用户名"`
}
// Validation error: "用户名 is required"
// Without label: "Username is required"嵌套参数
支持嵌套结构体:
go
// Address is a nested structure
type Address struct {
Street string `json:"street" validate:"required" label:"街道"`
City string `json:"city" validate:"required" label:"城市"`
ZipCode string `json:"zipCode" validate:"required,len=6" label:"邮编"`
}
// UserParams with nested address
type UserParams struct {
api.P
Username string `json:"username" validate:"required" label:"用户名"`
Address Address `json:"address" validate:"required"`
}数组参数
支持数组类型的参数:
go
// OrderParams with array of items
type OrderParams struct {
api.P
CustomerId string `json:"customerId" validate:"required" label:"客户ID"`
Items []OrderItem `json:"items" validate:"required,min=1,dive" label:"订单项"`
}
// OrderItem is validated for each element
type OrderItem struct {
ProductId string `json:"productId" validate:"required" label:"产品ID"`
Quantity int `json:"quantity" validate:"required,min=1" label:"数量"`
}dive 标签表示验证数组中的每个元素。
完整示例
go
package payloads
import (
"github.com/ilxqx/vef-framework-go/api"
"github.com/ilxqx/vef-framework-go/null"
)
// UserSearch for query operations
type UserSearch struct {
api.P
Username string `json:"username" search:"contains"`
Email string `json:"email" search:"contains"`
Status []string `json:"status" search:"in"`
IsActive *bool `json:"isActive" search:"eq"`
DeptId string `json:"deptId" search:"eq"`
}
// UserBaseParams shared fields
type UserBaseParams struct {
api.P
Username string `json:"username" validate:"required,alphanum,min=3,max=32" label:"用户名"`
Email string `json:"email" validate:"required,email,max=64" label:"邮箱"`
DisplayName null.String `json:"displayName" validate:"omitempty,max=64" label:"显示名称"`
Phone null.String `json:"phone" validate:"omitempty,len=11,numeric" label:"手机号"`
DeptId null.String `json:"deptId" label:"部门"`
RoleIds []string `json:"roleIds" label:"角色"`
IsActive bool `json:"isActive"`
}
// UserCreateParams for create operation
type UserCreateParams struct {
UserBaseParams `json:",inline"`
Password string `json:"password" validate:"required,min=6,max=32" label:"密码"`
PasswordConfirm string `json:"passwordConfirm" validate:"required,eqfield=Password" label:"确认密码"`
}
// UserUpdateParams for update operation
type UserUpdateParams struct {
UserBaseParams `json:",inline"`
Id string `json:"id"`
Password null.String `json:"password" validate:"omitempty,min=6,max=32" label:"密码"`
PasswordConfirm null.String `json:"passwordConfirm" validate:"omitempty,eqfield=Password" label:"确认密码"`
}