规范路由进阶:中间件、校验与统一返回的写法
引言
上一章的 Hello 示例能跑,但真实项目还需要:登录校验、参数校验失败时统一的错误响应、以及一致的返回结构。本章讲规范路由下这三件事怎么写。
概念
- 中间件挂载:规范路由注册在分组里,分组中间件(
group.Middleware)对其同样生效;g.Meta也支持在标签中声明中间件(如middleware:"Auth",其登记机制以官方文档规范路由章节为准)。 - 参数校验:Req 字段上的
v标签由框架在路由分发时自动执行,失败即返回错误,无需在方法体内手动校验。 - 统一返回:官方提供默认的规范路由响应处理中间件(脚手架中常见
s.Use(ghttp.MiddlewareHandlerResponse)),它把成功响应包装为code/message/data,把业务错误按错误码输出。规则细节以官方文档为准。
代码示例
带登录中间件、校验与统一返回的完整示例:
package main
import (
"context"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/net/ghttp"
)
// 登录校验中间件(与函数注册路由共用同一套写法)
func MiddlewareAuth(r *ghttp.Request) {
token := r.Get("token")
if token.IsEmpty() {
r.Response.WriteJson(g.Map{
"code": 401,
"message": "请先登录",
})
r.Exit()
return
}
r.Middleware.Next()
}
type UserGetReq struct {
g.Meta `path:"/user/{id}" method:"get" summary:"查询用户"`
Id int64 `v:"required" json:"id"`
Token string `v:"required" json:"token"`
}
type UserGetRes struct {
Id int64 `json:"id"`
Name string `json:"name"`
}
type User struct{}
func (User) Get(ctx context.Context, req *UserGetReq) (res *UserGetRes, err error) {
// 参数已自动校验:Id/Token 必填
return &UserGetRes{Id: req.Id, Name: "GoFrame"}, nil
}
func main() {
s := g.Server()
// 统一返回格式:把 res 包装为 {code,message,data}
s.Use(ghttp.MiddlewareHandlerResponse)
s.Group("/", func(group *ghttp.RouterGroup) {
group.Middleware(MiddlewareAuth)
group.Bind(new(User))
})
s.SetPort(8000)
s.Run()
}
访问测试:
# 不带 token:中间件直接拦截
curl "http://127.0.0.1:8000/user/1"
# 带 token 但缺 id:自动校验失败,返回校验错误
curl "http://127.0.0.1:8000/user/0?token=abc"
# 正常访问:得到统一格式的成功响应
curl "http://127.0.0.1:8000/user/1?token=abc"
方法内返回业务错误时,配合 gerror/gcode 返回带错误码的错误,统一返回中间件会把错误码与消息放进响应,业务方无需各自拼 JSON(用法见第 07 章)。
注意点
MiddlewareHandlerResponse是官方默认返回实现,也可在响应中间件里完全自定义返回结构。g.Meta标签中的summary等描述信息会用于接口文档生成(openapi/swagger)。- 校验标签写错规则名时运行期会报错,配置后务必先跑一个用例验证。
- 分组中间件与 meta 中间件叠加时,执行顺序规则与第 09 章一致,复杂场景先在文档里确认。
小结
规范路由进阶三件套:分组中间件做公共拦截、v 标签自动校验、官方响应中间件统一返回。配合 gerror/gcode,一套"声明式"接口工程就成型了。细节以官方文档 goframe.org 的规范路由章节为准。