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

zj972 · 2018-07-09 18:01:33 · 1417 次点击 · 大约8小时之前 开始浏览    置顶
这是一个创建于 2018-07-09 18:01:33 的主题,其中的信息可能已经有所发展或是发生改变。

package test

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

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

    type User struct {
        Id   int
        Name string
        Sex  string
    }
    users := []*User{}

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

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

    fmt.Printf("val: %v\n", val)
    fmt.Printf("typ: %v\n", typ)

    for _, r := range mList {
        mVal := reflect.Indirect(reflect.New(typ.Elem().Elem())).Addr()
        //fmt.Printf("mVal: %+v\n", mVal)
        for key, val := range r {
            err = setField(mVal.Interface(), key, val)
            if err != nil {
                return err
            }
        }
        //fmt.Printf("mVal: %+v\n", mVal)
        val = reflect.Append(val, mVal)
    }
    //echo: val: [0xc04206c2a0 0xc04206c390 0xc04206c480 0xc04206c570]
    fmt.Printf("val: %+v\n", val.Interface())
    model = val.Interface()
    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
}

有疑问加站长微信联系(非本文作者)

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

1417 次点击  
加入收藏 微博
5 回复  |  直到 2018-07-10 09:50:02
luominggao123
luominggao123 · #1 · 7年之前
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
}
zj972
zj972 · #2 · 7年之前
luominggao123luominggao123 #1 回复

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

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

luominggao123
luominggao123 · #3 · 7年之前

好吧,我的理解错了。

luominggao123
luominggao123 · #4 · 7年之前
package main

import (
    "bytes"
    "encoding/gob"
    "errors"
    "fmt"
    "reflect"
    "strings"
)

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": "男"},
    }

    type User struct {
        Id   int
        Name string
        Sex  string
    }
    users := []*User{}

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

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
            }
        }
        val = reflect.Append(val, mVal)
    }
    DeepCopy(model, val.Interface())
    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
}

func DeepCopy(dst, src interface{}) error {
    var buf bytes.Buffer
    if err := gob.NewEncoder(&buf).Encode(src); err != nil {
        return err
    }
    return gob.NewDecoder(bytes.NewBuffer(buf.Bytes())).Decode(dst)
}
zj972
zj972 · #5 · 7年之前
luominggao123luominggao123 #4 回复

``` package main import ( "bytes" "encoding/gob" "errors" "fmt" "reflect" "strings" ) 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": "男"}, } type User struct { Id int Name string Sex string } users := []*User{} mapToStruct(mList, &users) fmt.Printf("users: %+v\n", users) } 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 } } val = reflect.Append(val, mVal) } DeepCopy(model, val.Interface()) 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 } func DeepCopy(dst, src interface{}) error { var buf bytes.Buffer if err := gob.NewEncoder(&buf).Encode(src); err != nil { return err } return gob.NewDecoder(bytes.NewBuffer(buf.Bytes())).Decode(dst) } ```

谢谢你的答案。

添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传