'Storing field of struct accessed via reflection

I am picking up quest parameters for my game from a CSV. The parameters include a stat tracked, e.g. "CardsDeployed", and conditions for what kind of cards are valid for this quest. The condition might be something like "Cost:4" where Cost corresponds to a field in a struct inside my program:

type template struct {
    Cost int
    // other parameters
}

I have player stats that map card templates to the stats desired, e.g.

playerStats["CardsDeployed"] = map[template]uint{}

Given a quest condition, how do I filter this map for all templates that meet that condition? I know I can do this by reflecting on the concrete value of every template in the map, and accessing the desired field using the field name ("Cost"), but this seems very expensive (this is on the game server so has to be done frequently for many players). I cannot convert template to a generic map[string]interface{} because it is used throughout my code, and so I need it to be strongly typed.

TLDR: Is there a way to store a reference to the field of a struct type (here template) that can then be used to access that particular field from any concrete instance of that struct? I already know the struct layout and all the quests when my program runs, so in that case I only need to run the reflection once and store the field reference.

Please let me know if any further details would help. Thanks!



Solution 1:[1]

Since you mentioned that my comment was the solution that you went for to "solve" the problem. I reckon it should perhaps be an answer. So:

In the case that the field name is avaiable to you only as a string, you may be better off giving template a method GetValue(name string) or something and use a map[string]interface{} in the template struct to hold all the values. If on one end you have a large and dynamic list of field names, perhaps a struct with static field names is not the best way to store the data?

type template struct {
    data map[string]interface{}
}

func (t *template) GetValue(name string) interface{} {
   if v, ok := t.data[name]; ok {
      return v
   }
   return nil
}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1