账号密码登录
微信安全登录
微信扫描二维码登录

登录后绑定QQ、微信即可实现信息互通

手机验证码登录
找回密码返回
邮箱找回 手机找回
注册账号返回
其他登录方式
分享
  • 收藏
    X
    【golang】想用反射做一个map数组转结构体数组的方法,代码如下,怎么把反射生成的结构体加进数组里?
    45
    0

    描述

    想做一个类似于orm的数据组件,遇到这个问题,把一个[]map[string]interface{}的response转换成对应类型的结构体数组里面

    思路

    看了orm的源码,以及网上的一些文章,然后用反射完成了单个结构体赋值,也就是orm中的err := o.Read(&user),做数组时参考了orm中的func (o *rawSet) QueryRows(containers ...interface{}) (int64, error)

    相关代码

    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的值替换结构的值
    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
    打赏
    收藏
    点击回答
        全部回答
    • 0
    • 敏哥哥 普通会员 1楼

      在Go中,反射用于获取对象的信息,如类型、字段等。你可以使用反射获取map的键值对,并将其转换为结构体数组。以下是一个示例:

      ```go package main

      import ( "fmt" "反射" )

      type MapItem struct { Name string json:"name" Value int json:"value" }

      func main() { // 创建一个map var m map[string]int

      // 使用反射获取map的键值对
      for k, v := range m {
          // 将反射中的字段转换为结构体
      /item := MapItem{Name: k, Value: v}
          // 将结构体添加到数组中
          m[k] = append(m[k], item)
      }
      
      // 打印map的键值对
      for k, v := range m {
          fmt.Printf("%s:%d\n", k, v)
      }
      

      } ```

      这段代码首先创建了一个map,然后使用反射获取map的键值对。对于每个键值对,它使用反射中的json字段获取其对应的值,并将其转换为结构体MapItem。然后,它将这个结构体添加到map的对应键的值中。最后,它打印出map的键值对。

    • 李小不 普通会员 2楼

      在Go中,反射用于获取对象的信息,如类型、字段等。你可以使用反射获取map的键值对,并将其转换为结构体数组。以下是一个示例:

      ```go package main

      import ( "fmt" "反射" )

      type MapItem struct { Name string json:"name" Value int json:"value" }

      func main() { // 创建一个map var m map[string]int

      // 使用反射获取map的键值对
      for k, v := range m {
          // 将反射中的字段转换为结构体
      /item := MapItem{Name: k, Value: v}
          // 将结构体添加到数组中
          m[k] = append(m[k], item)
      }
      
      // 打印map的键值对
      for k, v := range m {
          fmt.Printf("%s:%d\n", k, v)
      }
      

      } ```

      这段代码首先创建了一个map,然后使用反射获取map的键值对。对于每个键值对,它使用反射中的json字段获取其对应的值,并将其转换为结构体MapItem。然后,它将这个结构体添加到map的对应键的值中。最后,它打印出map的键值对。

    更多回答
    扫一扫访问手机版
    • 回到顶部
    • 回到顶部