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

用反射从地图填充结构

用反射从地图填充结构

Go
隔江千里 2021-11-15 16:38:40
我有这样的地图 type Store map[string]string从这张地图中,我想填充一个结构。目标是,对于struct的每个字段,找到匹配字段名的key,取值,并根据struct字段的类型,将值转换为合适的struct字段类型并设置。基本上地图将包含整数,布尔值,字符串和持续时间作为字符串,因此转换应该简单strconv.atoi(),time.parseDuration()...另外,我想使用结构标签来指定地图中键的名称,因为结构字段可能是驼峰式,而地图中的键将是这样的“example_key”任何想法如何做到这一点。我已经阅读了关于 golang 反射的内容,但它对我来说仍然不透明。我只需要一个解释来解决这个问题,然后我想我可以自己处理实现。
查看完整描述

1 回答

?
慕莱坞森

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

为了避免在评论中进行一些扩展讨论,我将回答解释我将选择的两种方法。一般来说,我会避免反射方法。在某些情况下会调用它,但大多数情况下,越冗长、字面意思、简单的代码会更好,即使它多几行并且这些方法的功能之间存在一些重叠。


所以,从简单的例子开始。假设您有 3 种类型GroceryStore,ComputerStore、 和CornerStore。在每种类型定义的任何包中,定义一些类似方法的构造函数是相当常见的(它们在技术上不是构造函数,只是封装了实例化类型并返回它但目的相同的范围方法)。所以一个例子是;


func NewComputerStore(store Store) *ComputerStore {

      return &ComputerStore{

            Name: store["Name"],

            Location: store["Location"],

            //ect

      }

}

当然,上面的例子是完全不安全的。实际上,您需要使用v, ok := myMape["key"]语法,然后分配 ifok和 if not 执行任何操作(可能是分配默认值、记录错误和抛出错误的某种组合)。


现在如果你想要一个通用的方法......它通常看起来更像这样(注意这是未经测试的并且比工作示例更伪代码);


func (s *Store) ConvertToObject(obj interface{}) error {

    val := reflect.ValueOf(obj)

    for i := 0; i < val.NumField(); i++ {

        switch v := val.Field(i).(type) {

        case int64:

            val.Field(i).SetInt(strconv.Atoi(s[val.Field(i).Name]))

        }

    }

}

所以上面代码的基本思想是这样的。您从商店地图开始。调用者知道该映射应该是什么类型。他们调用此方法并传递该类型的新实例。在方法中,我们并不真正关心类型是什么,我们关心它的字段的类型是什么。所以我迭代传入的对象上的所有字段。每个字段都通过类型开关(因为对于结构中存在的每个类型,我都需要一个字符串到 X 的转换,这个方法应该使用,或者至少一个体面的基本情况),在每种类型的情况下,您可以使用字段名称进行分配以在Store地图中查找它的值并将其从字符串转换为 X。


希望这是有道理的。如果它没有真正阐明方法,我可以跟进。请记住,上面的代码不是要运行的。此外,我已经忽略了所有错误处理,您需要大量的错误处理才能使通用函数工作(如果转换失败该怎么办?如果类型不被识别怎么办?所有其他可能不常见的错误呢?地方?)。


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

添加回答

举报

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