go-zero API参数定义 + 参数校验
本节目标:掌握 goctl api 里三种最常用入参标签:
path、query、json,以及参数校验。 对应 Gin 里的path、form、json、binding,对比记忆。
一、三种参数标签总览
| 标签 | 含义 | 对应位置 | 适用请求 |
|---|---|---|---|
path:"name" |
路径参数 | /user/:id |
GET |
form:"name" |
URL查询参数 | /user?id=1&name=wang |
GET |
json:"name" |
JSON请求体 | {"name":"xxx"} |
POST/PUT |
规则:
- 一个结构体可以同时包含
path + query(GET接口常用)- POST接口一般只用
json,接收body- go-zero 自动根据 http 方法,自动解析对应位置参数
二、示例:同时带 path 和 query 参数(GET接口)
修改你的 user.api 文件,新增一个接口GetUserDetail
less
type UserReq {
Id int `path:"id"`
Name string `form:"name"`
}
type UserResp {
Name string
Age int
}
@server(
prefix: /api
)
service user-api {
@handler GetUser
get /user/:id (UserReq) returns (UserResp)
// 新增:获取用户详情,path参数id + query参数name
@handler GetUserDetail
get /user/detail/:id (UserReq) returns (UserResp)
}
保存api,执行代码生成:
bash
goctl api go -api user.api -dir .
⚠️ 生成会更新handler、types,不会覆盖logic。
写 logic 业务代码
打开 internal/logic/getuserdetaillogic.go
go
func (l *GetUserDetailLogic) GetUserDetail(req *types.UserReq) (*types.UserResp, error) {
// req.Id 来自路径 :id
// req.Name 来自url ?name=xxx
return &types.UserResp{
Name: fmt.Sprintf("用户:%s,编号%d", req.Name, req.Id),
Age: 20,
}, nil
}
重启服务测试:
arduino
curl "http://127.0.0.1:8888/api/user/detail/100?name=wang"
返回:
json
{"name":"用户:wang,编号100","age":20}
三、POST接口,JSON请求体(json标签)
继续在 user.api 增加创建用户接口
go
type CreateUserReq {
Username string `json:"username"`
Password string `json:"password"`
}
type CreateUserResp {
Uid int64 `json:"uid"`
}
// 放在service {}里面
@handler CreateUser
post /user/create (CreateUserReq) returns (CreateUserResp)
再次执行生成:
bash
goctl api go -api user.api -dir .
打开 internal/logic/createuserlogic.go
go
func (l *CreateUserLogic) CreateUser(req *types.CreateUserReq) (*types.CreateUserResp, error) {
// req.Username、req.Password 从json body中解析
l.Infof("收到创建用户请求,username=%s", req.Username)
return &types.CreateUserResp{
Uid: 10001,
}, nil
}
测试POST请求:
json
curl -X POST -H "Content-Type: application/json" -d '{"username":"zhangsan","password":"123456"}' [http://127.0.0.1:8888/api/user/create](http://127.0.0.1:8888/api/user/create)
返回:
json
{"uid":10001}
四、参数校验(重点,对应Gin binding)
go-zero 内置基于 validator 的校验,在tag增加 validate:"规则"
支持的常用规则:
required必填min=6最小长度gt=0数字大于0
修改CreateUserReq加上校验:
lua
type CreateUserReq {
Username string `json:"username" validate:"required,min=2"`
Password string `json:"password" validate:"required,min=6"`
}
✅含义:username必填,最少2个字符;password必填,最少6位。
重新执行生成命令。
go-zero 会自动在校验失败时,直接返回400错误,不需要手写if判断!
测试非法请求,密码太短:
json
curl -X POST -H "Content-Type: application/json" -d '{"username":"z","password":"123"}' [http://127.0.0.1:8888/api/user/create](http://127.0.0.1:8888/api/user/create)
服务直接返回校验错误,不需要业务代码判断。
yaml
vbnet
Name: user-api
Host: 0.0.0.0
Port: 8888
Author: long
Version: v1.0.0
在internal/config/config.go 配置对应的字段
go
type Config struct {
rest.RestConf
Author string
Version string
}
rest.RestConf:go-zero 内置的 http 服务配置,包含 Name、Host、Port
internal/svc/servicecontext.go会自动的加载配置参数
读取配置信息
go
func (l *GetUserLogic) GetUser(req *types.UserReq) (resp *types.UserResp, err error) {
// todo: add your logic here and delete this line
author := l.svcCtx.Config.Author
version := l.svcCtx.Config.Version
userIdStr := strconv.Itoa(req.Id)
return &types.UserResp{
Name: "用户" + userIdStr + " " + author + " " + version,
}, nil
}
参数校验 validate
太棒了🎉! 原理一句话记住:
不写yaml tag时,go-zero使用go的yaml库自动忽略大小写匹配;写了tag之后,就严格完全匹配(大小写敏感)。 所以你yaml写
Author,结构体字段Author,去掉tag直接就能映射上,省去大小写坑。
小结这个知识点(面试会问)
- 结构体字段首字母必须大写,否则私有,反射读不到;
- 有
yaml:"xxx"tag:严格匹配,大小写敏感; - 没有tag:自动按字段名忽略大小写映射;
- yaml缩进必须是空格,禁止tab,层级错直接读不到值。
现在访问接口:
ruby
curl [http://127.0.0.1:8888/api/user/100](http://127.0.0.1:8888/api/user/100)
你应该能拿到拼接好的 Name:用户100 long v1.0.0
第五节:go-zero 参数校验 validate(基于validator)
给请求结构体增加校验规则,客户端传非法参数,框架自动拦截,不用手写if判断。
go
go get github.com/go-playground/validator/v10
go mod tidy
1. 语法写在 api 文件里(goctl生成)
打开 user.api
python
type UserReq {
Id int `path:"id" validate:"required,gt=0"`
}
@server(
prefix: /api
)
service user-api {
@get("/user/:id")
GetUser(UserReq) returns (UserResp)
}
validate:"required":必填,不能空gt=0:greater than,必须大于0
执行goctl重新生成代码(只要api改了,都要重新生成handler/types)
bash
goctl api go -api user.api -dir .


生成后,types.go里的结构体自动带上validate标签。
2. 常用校验tag
ini
required 必填
gt=10 数字 > 10
gte=10 >=10
lt=10 <10
lte=10 <=10
email 邮箱格式
min=3 字符串最小长度
max=10 字符串最大长度
oneof=male female 只能是male或者female
3. 自动校验时机
go-zero的rest handler在进入你的logic之前自动执行校验 。 参数不合法,直接返回错误信息,logic代码根本不会执行。
测试:访问 /api/user/-1 Id=-1,不满足gt=0,直接返回400错误。
4. 自定义错误提示(可选)
lua
type UserReq {
Id int `path:"id" validate:"required,gt=0" msg:"id必须大于0"`
}
动手任务
- 修改user.api,给
UserReq加上validate校验validate:"required,gt=0" - goctl重新生成代码
- 测试正常:
/api/user/100 - 测试非法:
/api/user/-5,看是否直接返回参数错误
做完测试成功回复:好了,下一节,我们学习MySQL模型CRUD。
要不要我顺带讲一下,validate底层原理(go-zero怎么在进入logic前自动校验)?