规范路由进阶:中间件、校验与统一返回的写法

引言

上一章的 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 的规范路由章节为准。

笔记加载中…