想用反射做一个map数组转结构体数组的方法,代码如下,不知道怎么把反射生成的结构体加进数组里,求大佬帮忙

zj972 · 2018-07-09 18:01:33 · 1417 次点击

emmmm...你这样还要interface{}干嘛,你不能在方法里面调结构体呀,我这做的是一个组件,要支持任意类型的结构体。

#2
更多评论
package main

import (
    "errors"
    "fmt"
    "reflect"
    "strings"
)

type User struct {
    Id   int
    Name string
    Sex  string
}

var users []*User

func main() {
    mList := []map[string]interface{}{
        {"Id": 213, "Name": "zhaoliu", "Sex": "男"},
        {"Id": 56, "Name": "zhangsan", "Sex": "男"},
        {"Id": 7, "Name": "lisi", "Sex": "女"},
        {"Id": 978, "Name": "wangwu", "Sex": "男"},
    }

    mapToStruct(mList, &users)
    fmt.Printf("users: %+v\n", users[0])
}

func mapToStruct(mList []map[string]interface{}, model interface{}) (err error) {
    val := reflect.Indirect(reflect.ValueOf(model))
    typ := val.Type()

    for _, r := range mList {
        mVal := reflect.Indirect(reflect.New(typ.Elem().Elem())).Addr()

        for key, val := range r {
            err = setField(mVal.Interface(), key, val)

            if err != nil {
                return err
            }

        }

        v, ok := mVal.Interface().(*User)
        if ok {
            users = append(users, v)
        }
    }

    return err
}

//用map的值替换结构的值
func setField(obj interface{}, name string, value interface{}) error {
    // 将首字母转换为大写
    sl := strings.Split(name, "")
    sl[0] = strings.ToUpper(sl[0])
    name = strings.Join(sl, "")

    structValue := reflect.ValueOf(obj).Elem() //结构体属性值
    //fmt.Printf("structValue: %+v\n", structValue)
    structFieldValue := structValue.FieldByName(name) //结构体单个属性值
    //fmt.Printf("structFieldValue: %+v\n", structFieldValue)
    if !structFieldValue.IsValid() {
        return fmt.Errorf("No such field: %s in obj", name)
    }

    if !structFieldValue.CanSet() {
        return fmt.Errorf("Cannot set %s field value", name)
    }

    structFieldType := structFieldValue.Type() //结构体的类型
    val := reflect.ValueOf(value)              //map值的反射值

    if structFieldType != val.Type() {
        return errors.New("type is err")
    }

    structFieldValue.Set(val)
    return nil
}
#1

好吧,我的理解错了。

#3