请求参数(二):结构体接收与对象化请求处理
引言
接口参数一多,逐字段 r.Get 既啰嗦又容易漏。GoFrame 支持把请求参数直接绑定到一个 Go 结构体上,这一章讲结构体接收参数,以及更进一步的"对象化"处理思路。
概念
- 结构体绑定:定义与参数对应的结构体,调用
r.Parse(&req)即可完成绑定,字段名与参数名同名即自动匹配。 - 校验联动:结构体字段可以带
v标签声明校验规则(下一章 gvalid 展开),r.Parse发现校验失败会返回错误。 - 参数来源:
Parse默认综合 Query、Form、路由参数等来源做绑定(具体优先级与自定义映射标签以官方文档为准)。 - 对象化:把"入参结构体 + 处理函数"当成一个整体来设计,一个接口一个 Req 类型,代码即文档。规范路由(第 12 章)会把这种风格发挥到极致。
代码示例
一个带校验的结构体接收示例:
package main
import (
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/net/ghttp"
)
// 入参结构体:字段与请求参数同名即可自动绑定
type CreateUserReq struct {
Name string `v:"required"` // 必填
Age int `v:"between:1,150"` // 取值范围
Email string `v:"email"` // 邮箱格式
}
func main() {
s := g.Server()
s.Group("/user", func(group *ghttp.RouterGroup) {
group.POST("/create", func(r *ghttp.Request) {
var req CreateUserReq
if err := r.Parse(&req); err != nil {
// 绑定或校验失败,直接返回错误信息
r.Response.WriteJson(g.Map{"code": 1, "message": err.Error()})
return
}
r.Response.WriteJson(g.Map{
"code": 0,
"data": req, // 后续交给业务层处理
})
})
})
s.SetPort(8000)
s.Run()
}
测试:POST /user/create,表单体 name=john&age=20&email=john@example.com,正常返回结构体;把 name 去掉再请求,会收到 required 校验错误。
把"参数定义 + 处理"对象化一点——先定义独立的请求类型,业务函数只依赖结构体:
type CreateUserInput struct {
Name string
Age int
Email string
}
// 业务函数只关心结构体,不关心 HTTP 细节,便于单测复用
func createUser(input *CreateUserInput) error {
// 假设这里调用 service/dao 落库
return nil
}
注意点
Parse的目标必须是结构体指针:r.Parse(&req),写错会报错。- 布尔、数字字段在参数缺失时会取零值,需要区分"没传"与"传了 0"时可配合
*int指针或gvar字段。 v标签规则语法(required、between:1,150、email等)在下一章系统讲解。- 参数名与字段名不一致时的映射标签(如
p、json)写法与优先级,以官方文档请求输入章节为准。
小结
r.Parse(&req) 让"取参数"变成"填结构体",代码显著变短、可读性变好,也为参数校验和对象化设计铺路。下一章我们进入规范路由,看看 GoFrame 官方主推的接口定义方式。