猿问

用反射从地图填充结构

我有这样的地图 type Store map[string]string

从这张地图中,我想填充一个结构。目标是,对于struct的每个字段,找到匹配字段名的key,取值,并根据struct字段的类型,将值转换为合适的struct字段类型并设置。

基本上地图将包含整数,布尔值,字符串和持续时间作为字符串,因此转换应该简单strconv.atoi()time.parseDuration()...

另外,我想使用结构标签来指定地图中键的名称,因为结构字段可能是驼峰式,而地图中的键将是这样的“example_key”

任何想法如何做到这一点。我已经阅读了关于 golang 反射的内容,但它对我来说仍然不透明。我只需要一个解释来解决这个问题,然后我想我可以自己处理实现。


隔江千里
浏览 155回答 1
1回答

慕莱坞森

为了避免在评论中进行一些扩展讨论,我将回答解释我将选择的两种方法。一般来说,我会避免反射方法。在某些情况下会调用它,但大多数情况下,越冗长、字面意思、简单的代码会更好,即使它多几行并且这些方法的功能之间存在一些重叠。所以,从简单的例子开始。假设您有 3 种类型GroceryStore,ComputerStore、 和CornerStore。在每种类型定义的任何包中,定义一些类似方法的构造函数是相当常见的(它们在技术上不是构造函数,只是封装了实例化类型并返回它但目的相同的范围方法)。所以一个例子是;func NewComputerStore(store Store) *ComputerStore {&nbsp; &nbsp; &nbsp; return &ComputerStore{&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Name: store["Name"],&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Location: store["Location"],&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //ect&nbsp; &nbsp; &nbsp; }}当然,上面的例子是完全不安全的。实际上,您需要使用v, ok := myMape["key"]语法,然后分配 ifok和 if not 执行任何操作(可能是分配默认值、记录错误和抛出错误的某种组合)。现在如果你想要一个通用的方法......它通常看起来更像这样(注意这是未经测试的并且比工作示例更伪代码);func (s *Store) ConvertToObject(obj interface{}) error {&nbsp; &nbsp; val := reflect.ValueOf(obj)&nbsp; &nbsp; for i := 0; i < val.NumField(); i++ {&nbsp; &nbsp; &nbsp; &nbsp; switch v := val.Field(i).(type) {&nbsp; &nbsp; &nbsp; &nbsp; case int64:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; val.Field(i).SetInt(strconv.Atoi(s[val.Field(i).Name]))&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }}所以上面代码的基本思想是这样的。您从商店地图开始。调用者知道该映射应该是什么类型。他们调用此方法并传递该类型的新实例。在方法中,我们并不真正关心类型是什么,我们关心它的字段的类型是什么。所以我迭代传入的对象上的所有字段。每个字段都通过类型开关(因为对于结构中存在的每个类型,我都需要一个字符串到 X 的转换,这个方法应该使用,或者至少一个体面的基本情况),在每种类型的情况下,您可以使用字段名称进行分配以在Store地图中查找它的值并将其从字符串转换为 X。希望这是有道理的。如果它没有真正阐明方法,我可以跟进。请记住,上面的代码不是要运行的。此外,我已经忽略了所有错误处理,您需要大量的错误处理才能使通用函数工作(如果转换失败该怎么办?如果类型不被识别怎么办?所有其他可能不常见的错误呢?地方?)。
随时随地看视频慕课网APP

相关分类

Go
我要回答