refactor(valid): 重构参数绑定函数错误处理机制
- 将CustomBind函数改为直接返回泛型对象,移除错误返回值 - 将bindFromJSON和bindFromParams函数改为panic方式处理错误 - 修改CustomBindToMap和CustomBindStructAndMap函数以适应新的错误处理机制 - 更新.gitignore文件忽略规则格式 - 更新IDE缓存文件中的文件修改时间戳main v1.0.1004
parent
65aea30aa4
commit
d409dc0e2f
|
|
@ -3,10 +3,9 @@
|
||||||
.project
|
.project
|
||||||
.orig
|
.orig
|
||||||
.swp
|
.swp
|
||||||
.idea/
|
.idea
|
||||||
.settings/
|
.settings/
|
||||||
.vscode/
|
.vscode
|
||||||
bin/
|
|
||||||
**/.DS_Store
|
**/.DS_Store
|
||||||
gf
|
gf
|
||||||
main
|
main
|
||||||
|
|
|
||||||
|
|
@ -340,7 +340,7 @@
|
||||||
<entry key="file://$PROJECT_DIR$/valid/valid.go">
|
<entry key="file://$PROJECT_DIR$/valid/valid.go">
|
||||||
<value>
|
<value>
|
||||||
<ScannedPath>
|
<ScannedPath>
|
||||||
<option name="lastModified" value="1772004278917" />
|
<option name="lastModified" value="1772006460780" />
|
||||||
</ScannedPath>
|
</ScannedPath>
|
||||||
</value>
|
</value>
|
||||||
</entry>
|
</entry>
|
||||||
|
|
@ -379,6 +379,13 @@
|
||||||
</ScannedPath>
|
</ScannedPath>
|
||||||
</value>
|
</value>
|
||||||
</entry>
|
</entry>
|
||||||
|
<entry key="file://$PROJECT_DIR$/../gin_test/controller/home/index.go">
|
||||||
|
<value>
|
||||||
|
<ScannedPath>
|
||||||
|
<option name="lastModified" value="1772005679921" />
|
||||||
|
</ScannedPath>
|
||||||
|
</value>
|
||||||
|
</entry>
|
||||||
<entry key="file://$PROJECT_DIR$/../gin_test/router/homeRouter.go">
|
<entry key="file://$PROJECT_DIR$/../gin_test/router/homeRouter.go">
|
||||||
<value>
|
<value>
|
||||||
<ScannedPath>
|
<ScannedPath>
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,7 @@ func ValidToStruct[T any](c *gin.Context) (object *T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// CustomBind 自定义参数绑定,不使用Gin的ShouldBind
|
// CustomBind 自定义参数绑定,不使用Gin的ShouldBind
|
||||||
func CustomBind[T any](c *gin.Context) (*T, error) {
|
func CustomBind[T any](c *gin.Context) *T {
|
||||||
obj := new(T)
|
obj := new(T)
|
||||||
|
|
||||||
// 获取请求方法
|
// 获取请求方法
|
||||||
|
|
@ -43,40 +43,36 @@ func CustomBind[T any](c *gin.Context) (*T, error) {
|
||||||
contentType := c.GetHeader("Content-Type")
|
contentType := c.GetHeader("Content-Type")
|
||||||
if strings.Contains(contentType, "application/json") {
|
if strings.Contains(contentType, "application/json") {
|
||||||
// JSON格式请求体
|
// JSON格式请求体
|
||||||
if err := bindFromJSON(c, obj); err != nil {
|
bindFromJSON(c, obj)
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
} else if strings.Contains(contentType, "application/x-www-form-urlencoded") ||
|
} else if strings.Contains(contentType, "application/x-www-form-urlencoded") ||
|
||||||
strings.Contains(contentType, "multipart/form-data") {
|
strings.Contains(contentType, "multipart/form-data") {
|
||||||
// 表单格式请求体
|
// 表单格式请求体
|
||||||
if err := c.Request.ParseForm(); err != nil {
|
if err := c.Request.ParseForm(); err != nil {
|
||||||
return nil, fmt.Errorf("解析表单数据失败: %w", err)
|
panic(err)
|
||||||
}
|
}
|
||||||
params = c.Request.PostForm
|
params = c.Request.PostForm
|
||||||
} else {
|
} else {
|
||||||
// 默认尝试解析为表单
|
// 默认尝试解析为表单
|
||||||
if err := c.Request.ParseForm(); err != nil {
|
if err := c.Request.ParseForm(); err != nil {
|
||||||
return nil, fmt.Errorf("解析请求数据失败: %w", err)
|
panic(err)
|
||||||
}
|
}
|
||||||
params = c.Request.PostForm
|
params = c.Request.PostForm
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
return nil, fmt.Errorf("不支持的请求方法: %s", method)
|
panic(fmt.Sprintf("不支持的请求方法: %s", method))
|
||||||
}
|
}
|
||||||
|
|
||||||
// 如果不是JSON请求,则从params绑定
|
// 如果不是JSON请求,则从params绑定
|
||||||
if params != nil {
|
if params != nil {
|
||||||
if err := bindFromParams(obj, params); err != nil {
|
bindFromParams(c, obj, params)
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 验证参数
|
// 验证参数
|
||||||
if err := g.Validator().Data(obj).Run(c); err != nil {
|
if err := g.Validator().Data(obj).Run(c); err != nil {
|
||||||
return nil, gerror.Current(err)
|
panic(gerror.Current(err).Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
return obj, nil
|
return obj
|
||||||
}
|
}
|
||||||
|
|
||||||
// ValidToMap 验证参数并返回结构体
|
// ValidToMap 验证参数并返回结构体
|
||||||
|
|
@ -92,12 +88,9 @@ func ValidToMap[T any](c *gin.Context) (object map[string]any) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// CustomBindToMap 自定义参数绑定到map
|
// CustomBindToMap 自定义参数绑定到map
|
||||||
func CustomBindToMap[T any](c *gin.Context) (map[string]any, error) {
|
func CustomBindToMap[T any](c *gin.Context) map[string]any {
|
||||||
obj, err := CustomBind[T](c)
|
obj := CustomBind[T](c)
|
||||||
if err != nil {
|
return gconv.Map(obj)
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return gconv.Map(obj), nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ValidToStructAndMap 验证参数并返回map
|
// ValidToStructAndMap 验证参数并返回map
|
||||||
|
|
@ -113,20 +106,17 @@ func ValidToStructAndMap[T any](c *gin.Context) (stru *T, object map[string]any)
|
||||||
}
|
}
|
||||||
|
|
||||||
// CustomBindStructAndMap 自定义参数绑定并返回结构体和map
|
// CustomBindStructAndMap 自定义参数绑定并返回结构体和map
|
||||||
func CustomBindStructAndMap[T any](c *gin.Context) (*T, map[string]any, error) {
|
func CustomBindStructAndMap[T any](c *gin.Context) (*T, map[string]any) {
|
||||||
obj, err := CustomBind[T](c)
|
obj := CustomBind[T](c)
|
||||||
if err != nil {
|
return obj, gconv.Map(obj)
|
||||||
return nil, nil, err
|
|
||||||
}
|
|
||||||
return obj, gconv.Map(obj), nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// bindFromJSON 从JSON请求体绑定参数
|
// bindFromJSON 从JSON请求体绑定参数
|
||||||
func bindFromJSON[T any](c *gin.Context, obj *T) error {
|
func bindFromJSON[T any](c *gin.Context, obj *T) {
|
||||||
// 读取请求体
|
// 读取请求体
|
||||||
body, err := io.ReadAll(c.Request.Body)
|
body, err := io.ReadAll(c.Request.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("读取请求体失败: %w", err)
|
panic(fmt.Sprintf("JSON解析失败:%v", err))
|
||||||
}
|
}
|
||||||
|
|
||||||
// 恢复请求体,以便后续使用
|
// 恢复请求体,以便后续使用
|
||||||
|
|
@ -134,22 +124,20 @@ func bindFromJSON[T any](c *gin.Context, obj *T) error {
|
||||||
|
|
||||||
// 解析JSON
|
// 解析JSON
|
||||||
if err := json.Unmarshal(body, obj); err != nil {
|
if err := json.Unmarshal(body, obj); err != nil {
|
||||||
return fmt.Errorf("JSON解析失败: %w", err)
|
panic(fmt.Sprintf("JSON解析失败:%v", err))
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// bindFromParams 从参数映射绑定到结构体
|
// bindFromParams 从参数映射绑定到结构体
|
||||||
func bindFromParams(obj any, params map[string][]string) error {
|
func bindFromParams(c *gin.Context, obj any, params map[string][]string) {
|
||||||
objValue := reflect.ValueOf(obj)
|
objValue := reflect.ValueOf(obj)
|
||||||
if objValue.Kind() != reflect.Ptr {
|
if objValue.Kind() != reflect.Ptr {
|
||||||
return fmt.Errorf("目标必须是指针类型")
|
panic("目标必须为指针")
|
||||||
}
|
}
|
||||||
|
|
||||||
objValue = objValue.Elem()
|
objValue = objValue.Elem()
|
||||||
if objValue.Kind() != reflect.Struct {
|
if objValue.Kind() != reflect.Struct {
|
||||||
return fmt.Errorf("目标必须是指向结构体的指针")
|
panic("目标必须指向结构体")
|
||||||
}
|
}
|
||||||
|
|
||||||
objType := objValue.Type()
|
objType := objValue.Type()
|
||||||
|
|
@ -192,11 +180,9 @@ func bindFromParams(obj any, params map[string][]string) error {
|
||||||
|
|
||||||
// 根据字段类型进行转换
|
// 根据字段类型进行转换
|
||||||
if err := setFieldValue(fieldValue, paramValue); err != nil {
|
if err := setFieldValue(fieldValue, paramValue); err != nil {
|
||||||
return fmt.Errorf("设置字段 %s 失败: %w", paramName, err)
|
panic(fmt.Sprintf("参数 %s 转换失败: %v", paramName, err))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// setFieldValue 设置字段值
|
// setFieldValue 设置字段值
|
||||||
|
|
@ -207,25 +193,25 @@ func setFieldValue(field reflect.Value, value string) error {
|
||||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||||
intValue, err := strconv.ParseInt(value, 10, 64)
|
intValue, err := strconv.ParseInt(value, 10, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
panic(err)
|
||||||
}
|
}
|
||||||
field.SetInt(intValue)
|
field.SetInt(intValue)
|
||||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
|
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
|
||||||
uintValue, err := strconv.ParseUint(value, 10, 64)
|
uintValue, err := strconv.ParseUint(value, 10, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
panic(err)
|
||||||
}
|
}
|
||||||
field.SetUint(uintValue)
|
field.SetUint(uintValue)
|
||||||
case reflect.Float32, reflect.Float64:
|
case reflect.Float32, reflect.Float64:
|
||||||
floatValue, err := strconv.ParseFloat(value, 64)
|
floatValue, err := strconv.ParseFloat(value, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
panic(err)
|
||||||
}
|
}
|
||||||
field.SetFloat(floatValue)
|
field.SetFloat(floatValue)
|
||||||
case reflect.Bool:
|
case reflect.Bool:
|
||||||
boolValue, err := strconv.ParseBool(value)
|
boolValue, err := strconv.ParseBool(value)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
panic(err)
|
||||||
}
|
}
|
||||||
field.SetBool(boolValue)
|
field.SetBool(boolValue)
|
||||||
case reflect.Slice:
|
case reflect.Slice:
|
||||||
|
|
@ -235,11 +221,11 @@ func setFieldValue(field reflect.Value, value string) error {
|
||||||
// 创建元素并设置值
|
// 创建元素并设置值
|
||||||
element := newValue.Index(0)
|
element := newValue.Index(0)
|
||||||
if err := setFieldValue(element, value); err != nil {
|
if err := setFieldValue(element, value); err != nil {
|
||||||
return err
|
panic(err)
|
||||||
}
|
}
|
||||||
field.Set(newValue)
|
field.Set(newValue)
|
||||||
default:
|
default:
|
||||||
return fmt.Errorf("不支持的字段类型: %v", field.Kind())
|
panic(fmt.Sprintf("不支持的字段类型: %v", field.Kind()))
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue