- 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
}
- 共 0 条
- 全部回答
-
敏哥哥 普通会员 1楼
在Go中,反射用于获取对象的信息,如类型、字段等。你可以使用反射获取map的键值对,并将其转换为结构体数组。以下是一个示例:
```go package main
import ( "fmt" "反射" )
type MapItem struct { Name string
json:"name"Value intjson:"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 intjson:"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的键值对。
- 扫一扫访问手机版
回答动态

- 神奇的四哥:发布了悬赏问题阿里云幻兽帕鲁服务器更新之后。服务器里面有部分玩家要重新创建角色是怎么回事啊?预计能赚取 0积分收益

- 神奇的四哥:发布了悬赏问题函数计算不同地域的是不能用内网吧?预计能赚取 0积分收益

- 神奇的四哥:发布了悬赏问题ARMS可以创建多个应用嘛?预计能赚取 0积分收益

- 神奇的四哥:发布了悬赏问题在ARMS如何申请加入公测呀?预计能赚取 0积分收益

- 神奇的四哥:发布了悬赏问题前端小程序接入这个arms具体是如何接入监控的,这个init方法在哪里进行添加?预计能赚取 0积分收益

- 神奇的四哥:发布了悬赏问题阿里云幻兽帕鲁服务器刚到期,是不是就不能再导出存档了呢?预计能赚取 0积分收益

- 神奇的四哥:发布了悬赏问题阿里云幻兽帕鲁服务器的游戏版本不兼容 尝试更新怎么解决?预计能赚取 0积分收益

- 神奇的四哥:发布了悬赏问题阿里云幻兽帕鲁服务器服务器升级以后 就链接不上了,怎么办?预计能赚取 0积分收益

- 神奇的四哥:发布了悬赏问题阿里云幻兽帕鲁服务器转移以后服务器进不去了,怎么解决?预计能赚取 0积分收益

- 神奇的四哥:发布了悬赏问题阿里云幻兽帕鲁服务器修改参数后游戏进入不了,是什么情况?预计能赚取 0积分收益
- 回到顶部
- 回到顶部

