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)
}