面试题答案
一键面试实现思路
- 获取结构体的反射值对象和反射类型对象。
- 遍历HTTP请求参数。
- 对于每个参数,在结构体的反射类型中查找对应的字段。
- 如果找到对应的字段,根据字段的类型将参数值转换为合适的类型,并设置到结构体的反射值对象对应的字段上。
示例代码
package main
import (
"fmt"
"net/http"
"reflect"
"strconv"
)
type Request struct {
ID int `param:"id"`
Name string `param:"name"`
}
func bindParams(r *http.Request, target interface{}) error {
err := r.ParseForm()
if err != nil {
return err
}
valueOf := reflect.ValueOf(target).Elem()
typeOf := reflect.TypeOf(target).Elem()
for i := 0; i < typeOf.NumField(); i++ {
field := typeOf.Field(i)
paramName := field.Tag.Get("param")
if paramName == "" {
continue
}
values := r.Form[paramName]
if len(values) == 0 {
continue
}
fieldValue := valueOf.Field(i)
switch fieldValue.Kind() {
case reflect.Int:
num, err := strconv.Atoi(values[0])
if err != nil {
return err
}
fieldValue.SetInt(int64(num))
case reflect.String:
fieldValue.SetString(values[0])
}
}
return nil
}
你可以使用以下方式调用:
func main() {
r := &http.Request{
Form: map[string][]string{
"id": {"123"},
"name": {"example"},
},
}
var req Request
err := bindParams(r, &req)
if err != nil {
fmt.Println("绑定参数错误:", err)
return
}
fmt.Printf("ID: %d, Name: %s\n", req.ID, req.Name)
}