gin/router/controller.go

145 lines
4.1 KiB
Go
Raw Normal View History

2025-01-27 19:46:34 +08:00
// Package router ...
//
// Description : router ...
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 2025-01-27 15:29
package router
import (
"reflect"
)
// controller 解析controller有哪些方法要注册为接口
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 15:30 2025/1/27
type controller struct {
}
// Parse 执行解析
//
// 符合注册为借口的方法具有如下特征:
//
// 1. 函数接受两个入参, 第一个参数为 gin.Context , 第二个参数为 任意结构体指针, 但是必须声明 Meta 相关信息, 否则会报错
//
// 2. 函数有两个返回值, 第一个返回值为任意结构体/结构体指针(限制死不能为map/slice, 方便后续统一标准化) , 第二个返回值为 error , 代表处理的异常, 会自动适配 exception.IException 类型
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 15:31 2025/1/27
func (c controller) Parse(inputController any) map[string]UriConfig {
parseRes := make(map[string]UriConfig)
if nil == inputController {
return parseRes
}
controllerType := reflect.TypeOf(inputController)
controllerValue := reflect.ValueOf(inputController)
/*if controllerType.Kind() == reflect.Func {
2025-01-27 19:46:34 +08:00
// 直接函数注册
cfg, isNeedRegister := c.methodConfig(controllerType)
if isNeedRegister {
parseRes[cfg.Path] = cfg
}
return parseRes
}*/
2025-01-27 19:46:34 +08:00
if controllerType.Kind() == reflect.Ptr {
controllerValue = controllerValue.Elem()
}
/*if controllerValue.IsNil() {
2025-01-27 19:46:34 +08:00
return parseRes
}*/
2025-01-27 19:46:34 +08:00
for methodIdx := 0; methodIdx < controllerType.NumMethod(); methodIdx++ {
uriCfg, needRegister := c.methodConfig(controllerType.Method(methodIdx))
2025-01-27 19:46:34 +08:00
if !needRegister {
continue
}
uriCfg.ApiStructValue = controllerValue
2025-01-27 19:46:34 +08:00
parseRes[uriCfg.Path] = uriCfg
}
return parseRes
}
// methodConfig 解析方法配置, 要求函数格式, 两个参数, 两个返回值, 格式 : func(ctx *gin.Context, formData anyStruct[组合Meta]) (anyStruct|map[response], error)
//
// 参数 : 方法反射结果
//
// 返回值 : 第一个 -> 解析出的接口配置 第二个 -> 是否要注册为接口
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 16:05 2025/1/27
func (c controller) methodConfig(reflectMethod reflect.Method) (cfg UriConfig, needRegister bool) {
methodType := reflectMethod.Type
2025-01-27 19:46:34 +08:00
// num0: 函数声明
// num1: 第一个参数
// num2: 第二个参数
if methodType.NumIn() != 3 {
needRegister = false
return
}
// 第一个参数必须是 *gin.Context
if methodType.In(1).String() != GinContextType {
2025-01-27 19:46:34 +08:00
needRegister = false
return
}
// 解析第二个参数是组合Meta的form表单
formType := methodType.In(2)
if formType.Kind() == reflect.Ptr {
formType = methodType.In(2).Elem()
}
cfg.FormDataType = formType
2025-02-14 22:30:56 +08:00
_, metaFieldExist := formType.FieldByName(FieldNameMeta)
2025-01-27 19:46:34 +08:00
if !metaFieldExist {
needRegister = false
return
}
2025-02-14 22:30:56 +08:00
cfg.ResultDataType = methodType.Out(0)
if cfg.ResultDataType == nil {
}
if methodType.Out(1).Kind().String() != ErrorType {
2025-01-27 19:46:34 +08:00
// 判断是否是实现 error接口的方法
outputErrParse := false
for j := 0; j < methodType.Out(1).NumMethod(); j++ {
if methodType.Out(1).Method(j).Name == ErrorInterfaceFuncName && // 实现Error方法
methodType.Out(1).Method(j).Type.NumIn() == 0 && // 没有任何参数
2025-01-27 19:46:34 +08:00
methodType.Out(1).Method(j).Type.NumOut() == 1 && // 一个返回值
methodType.Out(1).Method(j).Type.Out(0).Kind().String() == reflect.String.String() {
outputErrParse = true
break
}
}
if !outputErrParse {
needRegister = false
return
2025-01-27 19:46:34 +08:00
}
}
cfg.ApiLogicFunc = reflectMethod
needRegister = true
2025-01-27 19:46:34 +08:00
return
}
2025-02-07 16:10:33 +08:00
// parseParamConfig 解析参数配置
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 14:35 2025/2/7
func (c controller) parseParamConfig(formDataType reflect.Type) []UriParam {
res := make([]UriParam, 0)
for i := 0; i < formDataType.NumField(); i++ {
structField := formDataType.Field(i)
if structField.Name == FieldNameMeta {
// Meta 字段, 忽略
continue
}
jsonTag := structField.Tag.Get("json")
if jsonTag == "" {
jsonTag = structField.Name
}
}
return res
}