当前位置: 首页 > news >正文

gin-路由handler封装思路

  • 约束handler入参和返回为func(ctx, req) (resp, error)。
  • 通过反射,封装handler,在调用前后写入入参和返回的处理。
package testing

import (
	"context"
	"fmt"
	"reflect"
	"strings"
	"testing"
)

type ReqParams struct {
	Name string
	Age  int
}

type RouteHandlers struct{}

func (r *RouteHandlers) Test(c *context.Context, req *ReqParams) {
	fmt.Println("req:", req)
}

type Router struct {
	Method reflect.Value // 请求中的handler
	Params reflect.Value // 请求参数
}

func TestReflact(t *testing.T) {
	controller := &RouteHandlers{}
	handlerRef := reflect.ValueOf(controller)
	if handlerRef.NumMethod() == 0 {
		// 结构体无方法,不进行后续处理
		return
	}
	hMap := make(map[string]map[string]Router)
	// 1.提取控制器名:TypeOf获取到含*的package.type的完整类型
	structName := reflect.TypeOf(controller).String()
	if strings.Contains(structName, ".") {
		structName = structName[strings.Index(structName, ".")+1:]
	}
	if hMap[structName] == nil {
		hMap[structName] = make(map[string]Router)
	}

	// 2.提取方法名:Method获取可操作目标(后续调用)
	// 提取入参,生成实例,后续进行前置校验
	for i := 0; i < handlerRef.NumMethod(); i++ {
		mCall := handlerRef.Method(i)
		mName := handlerRef.Type().Method(i).Name
		// 人为约束:2个参数,第一个为context,第二个为请求参数
		reqParams := reflect.New(mCall.Type().In(1).Elem())

		// 亦可约束返回参数,做出统一处理:reflect.New(mCall.Type().Out().Elem())

		hMap[structName][mName] = Router{
			Method: mCall,
			Params: reqParams,
		}
	}
	fmt.Println(hMap)
	// 模拟请求时的调用
	c := context.TODO()
	hMap[structName]["Test"].Method.Call([]reflect.Value{reflect.ValueOf(&c), hMap[structName]["Test"].Params})

	// 后续封装func(r Router)func(c *gin.Context),返回gin可使用的handler时,写入下述参数验证
	//
	// 参数为 *A
	// reflect.New  => 生成一个指针,指向类型零值,req = **A
	// req.Interface => 返回req的实际值,并用interface包装,**A -> *A,再var i interface = *A
	// req.Elem => 返回interface或point指向的实际值,*A
	// if err := c.ShouldBindJson(r.Params.Interface()); err != nil {
	//     c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
	//     c.Abort()
	// 	   return
	// } else {
	//     args := []reflect.Value{reflect.ValueOf(c), r.Params.Elem()}
	//	   r.Method.Call(args)
	// }
}

相关文章:

  • upload-labs靶场学习记录2
  • OpenCV图像拼接(2)基于羽化(feathering)技术的图像融合算法拼接类cv::detail::FeatherBlender
  • CVPR2025 | 对抗样本智能安全方向论文汇总 | 持续更新中~
  • 《C++智能指针:建议使用 make_shared 代替 shared_ptr》
  • PostgreSQL 数据库源码编译安装全流程详解 Linux 8
  • SysVinit和Systemd的系统运行级别
  • 探秘 WRF DA:多维度剖析其在气象研究中的卓越效能
  • C++具名转型的功能和用途
  • 奇怪的异形选项卡样式、弧形边框选项卡
  • Go语言中package的使用规则《二》
  • java基础之windows电脑基础命令
  • 【其他】在线安装DataEase后无法远程访问
  • k近邻图(knn-graph)和局部线性嵌入图(LLE-graph)的相似性和区别
  • Python JSON模块loads、load、dump、dumps详解
  • Sql Server 索引性能优化 分析以及分表
  • 【LeetCode】大厂面试算法真题回忆(37)--知识图谱新词挖掘
  • 大数据从入门到入魔系列————探索大数据前世今生之迷
  • Unity | 游戏数据配置
  • SpringBoot整合MQTT最详细版(亲测有效)
  • 创建自己的github.io
  • 我国首部《人工智能气象应用服务办法》今天发布
  • 暗蓝评《性别打结》丨拆解性别之结需要几步?
  • 杨国荣︱学术上的立此存照——《故旧往事,欲说还休》读后
  • 2025上海体育消费节启动,多形式联动打造体育消费盛宴
  • 俄罗斯延长非法滞留外国人限期离境时间至9月
  • 跨海论汉|专访白馥兰:对中国农业史的兴趣,从翻译《齐民要术》开始