将地图转换为结构 [英] Converting map to struct

查看:82
本文介绍了将地图转换为结构的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图在Go中创建一个通用方法,它将使用来自 map [string] interface {}的数据填充 struct code>。例如,方法签名和用法可能如下所示:

  func FillStruct(数据映射[字符串]接口{},结果接口{}){
...
}

类型MyStruct结构{
名称字符串
年龄int64
}

myData:= make(map [string] interface {})
myData [Name] =Tony
myData [Age] = 23

结果:=& MyStruct {}
FillStruct(myData,result)

//结果现在将Name设置为Tony,Age设置为23

我知道这可以使用JSON作为中介来完成;是否还有另一种更有效的方法呢?

解决方案

这与西蒙的回答是一样的,但有一点错误处理:

http://play.golang.org/p/tN8mxT_V9h

  func SetField(obj interface {},name string,value interface {})error {
structValue:= reflect.ValueOf(obj).Elem()
structFieldValue:= structValue.FieldByName(name)

if!structFieldValue.IsValid(){
return fmt.Errorf (没有这样的字段:%s在obj中,名称)
}

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

structFieldType:= structFieldValue.Type()
val:= reflect.ValueOf(value)
如果structFieldType!= val.Type (){
return errors.New(提供的值类型不匹配obj字段类型)
}

st ructFieldValue.Set(val)
返回nil
}

类型MyStruct结构{
名称字符串
年龄int64
}

func(s * MyStruct)FillStruct(m map [string] interface {})error {
for k,v:= range m {
err:= SetField(s,k,v )
如果err!= nil {
返回err
}
}
返回nil
}

func main() {
myData:= make(map [string] interface {})
myData [Name] =Tony
myData [Age] = int64(23)

结果:=& MyStruct {}
err:= result.FillStruct(myData)
if err!= nil {
fmt.Println(err)
}
fmt.Println(结果)
}


I am trying to create a generic method in Go that will fill a struct using data from a map[string]interface{}. For example, the method signature and usage might look like:

func FillStruct(data map[string]interface{}, result interface{}) {
    ...
}

type MyStruct struct {
    Name string
    Age  int64
}

myData := make(map[string]interface{})
myData["Name"] = "Tony"
myData["Age"]  = 23

result := &MyStruct{}
FillStruct(myData, result)

// result now has Name set to "Tony" and Age set to 23

I know this can be done using JSON as an intermediary; is there another more efficient way of doing this?

解决方案

This is the same idea as Simon's answer, but with a little more error handling:

http://play.golang.org/p/tN8mxT_V9h

func SetField(obj interface{}, name string, value interface{}) error {
    structValue := reflect.ValueOf(obj).Elem()
    structFieldValue := structValue.FieldByName(name)

    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)
    if structFieldType != val.Type() {
        return errors.New("Provided value type didn't match obj field type")
    }

    structFieldValue.Set(val)
    return nil
}

type MyStruct struct {
    Name string
    Age  int64
}

func (s *MyStruct) FillStruct(m map[string]interface{}) error {
    for k, v := range m {
        err := SetField(s, k, v)
        if err != nil {
            return err
        }
    }
    return nil
}

func main() {
    myData := make(map[string]interface{})
    myData["Name"] = "Tony"
    myData["Age"] = int64(23)

    result := &MyStruct{}
    err := result.FillStruct(myData)
    if err != nil {
        fmt.Println(err)
    }
    fmt.Println(result)
}

这篇关于将地图转换为结构的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆