为了账号安全,请及时绑定邮箱和手机立即绑定

将映射转换为结构

将映射转换为结构

Go
拉风的咖菲猫 2021-11-22 19:41:23
好吧,标题有点误导。我所追求的如下:type MyStruct struct {    id   int    name string    age  int}func CreateFromMap(m map[string]interface{}) (MyStruct, error) {    var (        id   int        name string        age  int        ok   bool    )    err := errors.New("Error!")    id, ok = m["id"].(int)    if !ok {        return nil, err    }    name, ok = m["name"].(string)    if !ok {        return nil, err    }    age, ok = m["age"].(int)    if !ok {        return nil, err    }    return MyStruct{id, name, age}, nil}不要问:为什么我不使用CreateFromMap(int, string, int). 那个物体来自其他地方,不在我的控制范围内。将映射中的每个键值对映射到结构体属性已经很无聊了。但是ok在每次转换后检查是否一切正常是混乱的。除了反射之外,还有没有更简单的方法可以做到这一点?
查看完整描述

2 回答

?
繁星coding

TA贡献1797条经验 获得超4个赞

假设我假设您不想使用反射,因为您不想自己做。在这种情况下,如何使用为您执行此操作的外部包?


package main


import "fmt"

import "github.com/mitchellh/mapstructure"


type MyStruct struct {

    Id   int

    Name string

    Age  int

}


func main() {

    var m = make(map[string]interface{})

    m["Id"] = 17

    m["Name"] = "foo"

    m["Age"] = 42

    fmt.Printf("%+v\n", m)


    res, err := CreateFromMap(m)

    if err != nil {

        fmt.Println(err)

        return

    }

    fmt.Printf("%+v\n", res)

}


func CreateFromMap(m map[string]interface{}) (MyStruct, error) {

    var result MyStruct

    err := mapstructure.Decode(m, &result)

    return result, err

}

输出:


map[Age:42 Name:foo Id:17]

{Id:17 Name:foo Age:42}

无论您的结构是什么样子,它都有优势,但它在内部使用反射。实际上,如果不对结构的每个属性使用反射和/或重复代码,我看不到任何“好”的方法来做您想做的事情。但是,缺点是您必须使用大写的属性,以便将它们导出到外部包。


编辑(在评论中回答您的问题):

在我看来,如果要在“创建”结构时指定附加规则,应该在解码操作之后。例如:


func CreateFromMap(m map[string]interface{}) (MyStruct, error) {

    var result MyStruct

    err := mapstructure.Decode(m, &result)

    if err != nil {

         return result, err

    }

    if result.Age <= 0 {

        result.Age = 0

    }

    if result.Name == "" {

        return result, errors.New("empty name is not allowed")

    }


    return result, err

}

这样,您将清楚地将“转换”部分与您的结构的特定规则处理分开。


查看完整回答
反对 回复 2021-11-22
?
jeck猫

TA贡献1909条经验 获得超7个赞

你可以只编组/解组,但属性名称应该匹配


func CreateFromMap(m map[string]interface{}) (MyStruct, error) {

    data, _ := json.Marshal(m)

    var result MyStruct

    err := json.Unmarshal(data, &result)

    return result, err

}


查看完整回答
反对 回复 2021-11-22
  • 2 回答
  • 0 关注
  • 129 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信