鍍金池/ 問答/GO  網(wǎng)絡(luò)安全/ 【golang】想用反射做一個(gè)map數(shù)組轉(zhuǎn)結(jié)構(gòu)體數(shù)組的方法,代碼如下,怎么把反射

【golang】想用反射做一個(gè)map數(shù)組轉(zhuǎn)結(jié)構(gòu)體數(shù)組的方法,代碼如下,怎么把反射生成的結(jié)構(gòu)體加進(jìn)數(shù)組里?

描述

想做一個(gè)類似于orm的數(shù)據(jù)組件,遇到這個(gè)問題,把一個(gè)[]map[string]interface{}的response轉(zhuǎn)換成對應(yīng)類型的結(jié)構(gòu)體數(shù)組里面

思路

看了orm的源碼,以及網(wǎng)上的一些文章,然后用反射完成了單個(gè)結(jié)構(gòu)體賦值,也就是orm中的err := o.Read(&user),做數(shù)組時(shí)參考了orm中的func (o *rawSet) QueryRows(containers ...interface{}) (int64, error)

相關(guān)代碼

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)
    }
    fmt.Printf("val: %+v\n", val.Interface())
    //model = val.Interface()
    return err
}

//用map的值替換結(jié)構(gòu)的值
func setField(obj interface{}, name string, value interface{}) error {
    // 將首字母轉(zhuǎn)換為大寫
    sl := strings.Split(name, "")
    sl[0] = strings.ToUpper(sl[0])
    name = strings.Join(sl, "")

    structValue := reflect.ValueOf(obj).Elem() //結(jié)構(gòu)體屬性值
    //fmt.Printf("structValue: %+v\n", structValue)
    structFieldValue := structValue.FieldByName(name) //結(jié)構(gòu)體單個(gè)屬性值
    //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() //結(jié)構(gòu)體的類型
    val := reflect.ValueOf(value)              //map值的反射值

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

    structFieldValue.Set(val)
    return nil
}
回答
編輯回答