go使用反射获取http.Request参数到结构体

1. 为什么写这个工具

公司代码使用go原生写的,没有使用框架,接收前端的代码都使用的是req.FormValue()来接收,我觉得写了太多的接收参数的重复代码

2. Go代码
go 复制代码
// ParseParams 解析前端传的参数到结构体
func ParseParams[T any](req *http.Request) (T, error) {
	var t T
	tType := reflect.TypeOf(t)
	tValue := reflect.ValueOf(&t).Elem()

	if tType.Kind() != reflect.Struct {
		return t, fmt.Errorf("parseParams err: tType.Kind() != reflect.Struct")
	}

	for i := 0; i < tType.NumField(); i++ {
		field := tType.Field(i)
		value := tValue.Field(i)
		err := setFieldValue(field, value, req)
		if err != nil {
			return t, err
		}
	}

	return t, nil
}

// 设置对应的字段值
// 仅支持string, int, int64, int32, slice
func setFieldValue(field reflect.StructField, value reflect.Value, req *http.Request) error {
	formValue := req.FormValue(field.Tag.Get("json"))
	switch field.Type.Kind() {
	case reflect.String:
		value.SetString(formValue)
	case reflect.Int, reflect.Int64, reflect.Int32:
		atoi, err := strconv.Atoi(formValue)
		if err != nil {
			return fmt.Errorf("setFieldValue err: strconv.Atoi(%s) err: %v, field.Name: %v", formValue, err, field.Name)
		}
		value.SetInt(int64(atoi))
	case reflect.Slice:
		newSlice := reflect.New(field.Type)
		if err := json.Unmarshal([]byte(formValue), newSlice.Interface()); err != nil {
			return fmt.Errorf("setFieldValue err: json.Unmarshal(%s) err: %v, field.Name: %v", formValue, err, field.Name)
		}
		value.Set(newSlice.Elem())
	default:
		return fmt.Errorf("setFieldValue err: field.Type.Kind() not support: %v, field.Name: %v", field.Type.Kind(), field.Name)
	}

	return nil
}
3.使用
go 复制代码
type TestReq struct {
	ID           int32   `json:"id"`
	Name         string  `json:"name"`
	SiteIdList   []int32 `json:"siteIdList"`
	DateTimeList []int64 `json:"dateTimeList"`
}

func TestParseParams(t *testing.T) {
	req := &http.Request{}
	req.Form = map[string][]string{
		"id":           {"1"},
		"name":         {"test"},
		"siteIdList":   {"[1,2,3]"},
		"dateTimeList": {"[1694560000, 1694560060]"},
	}
	params, err := ParseParams[TestReq](req)
	if err != nil {
		fmt.Println(err)
		return
	}

	fmt.Println(params)
}
目前只做了我常用的一些变量,后续可能会加入其他变量和字段校验
相关推荐
caimouse几秒前
ReactOS 图形系统分析(33):字体子系统 — font.c
c语言·开发语言·reactos
圣殿骑士-Khtangc5 分钟前
Go-Channel面试精讲从底层结构到select随机性
golang
cxr82814 分钟前
HyperMind Lab M1 架构地基 Implementation Plan <二>
开发语言·人工智能·架构
特立独行的猫a22 分钟前
Tauri v2的Rust应用 → HarmonyOS(鸿蒙 PC)移植30分钟速成指南
开发语言·rust·harmonyos·tauri·移植·鸿蒙pc
迷迭香yy26 分钟前
大宗交易折溢价因子怎么挖掘本地化Python全流程实战
开发语言·人工智能·python
xieliyu.31 分钟前
UPD协议结构以及开发中注意事项
java·开发语言·笔记·java-ee
北漂燕郊杨哥32 分钟前
dsh-desktop:DeepSeek Harness 的本地优先桌面应用
golang·wails·deepseek·deepseekharness
Yweir35 分钟前
AI大模型开发-Python介绍、版本说明
开发语言·人工智能·python
峥嵘life9 小时前
Android16 311Y3 EAP-TLS 网络连接失败分析与修复总结
android·开发语言·人工智能·php
mqiqe11 小时前
AgentScope Java Harness:4. 双层记忆系统 让 Agent 拥有真正的“长期大脑“
java·开发语言