doujianzhi3358 2015-10-14 22:25
浏览 60
已采纳

使用反射从地图填充结构

I have a map of this kind type Store map[string]string

From this map, i would like to fill a struct. The goal is, for each field of the struct, find the key that match the field name, take the value, and based on the type of the struct field, convert the value to the proper struct field type and set it.

Basically the map will contains integers, booleans, strings and durations as strings so the convestion should be simply strconv.atoi(), time.parseDuration() ...

Also, i would like to use the structs tags to specify the name of the key in the map, because the struct field will be likely camelCase, while the keys in the map will be like this "example_key"

Any idea of how doing this. I have read about golang reflection but it is still opaque for me. I would just need an explanation to approach the problem, and then i think i can handle the implementation by my own.

Thanks

  • 写回答

1条回答 默认 最新

  • doufen1933 2015-10-14 23:15
    关注

    To avoid some extended discussion in comments I'm just going to make an answer explaining the two approaches I would choose from. Generally speaking, I would avoid the reflective method. There are cases where it is called for but most of the time the more verbose, literal, simple code will be better, even if it's a few more lines and there is some overlap between what the methods do.

    So, starting with the simple example. Suppose you got 3 types, GroceryStore, ComputerStore, and CornerStore. In whatever package each type is defined in, it is fairly common to define some constructor like methods (they're not technically constructors, just package scoped methods that instantiate a type and return it but same purpose). So an example would be;

    func NewComputerStore(store Store) *ComputerStore {
          return &ComputerStore{
                Name: store["Name"],
                Location: store["Location"],
                //ect
          }
    }
    

    Of course the example above is completely unsafe. In reality you need to use the v, ok := myMape["key"] syntax and then assign if ok and do whatever if not (probably some combination of assign default value, log error, and throw error).

    Now if you want a generalized method... It typically look something more like this (note this is untested and is more pseudo code than a working example);

    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]))
            }
        }
    }
    

    So the basic idea of the code above is this. You're starting with a store map. The caller knows what type that map is supposed to be. They call this method passing a new instance of that type. In the method we don't really care what the type is, we care what the type of it's fields are. So I iterate all the fields on the object passed in. Each field is put through the type switch (since I'll need a string to X conversion for every type that is present in the structs this method should work with, or at least a decent base case), in the case for each type you can do assignment using the field name to look up it's value in the Store map and converting from string to X.

    Hope that makes sense. I can follow up if it doesn't really clarify the approach. Remember the code above is not intended to run. Also, I've ignored all error handling which you will need lots of to make a generalized function work (what to do if conversion fails? What if type isn't recognized? What about all the other possible errors that won't be common place?).

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 BP神经网络控制倒立摆
  • ¥20 要这个数学建模编程的代码 并且能完整允许出来结果 完整的过程和数据的结果
  • ¥15 html5+css和javascript有人可以帮吗?图片要怎么插入代码里面啊
  • ¥30 Unity接入微信SDK 无法开启摄像头
  • ¥20 有偿 写代码 要用特定的软件anaconda 里的jvpyter 用python3写
  • ¥20 cad图纸,chx-3六轴码垛机器人
  • ¥15 移动摄像头专网需要解vlan
  • ¥20 access多表提取相同字段数据并合并
  • ¥20 基于MSP430f5529的MPU6050驱动,求出欧拉角
  • ¥20 Java-Oj-桌布的计算