代表许多领域的最优雅的方式

So, I have this list of attributes that I would like to represent in my Go code. That is, I'm looking for some data structure that can convey all these.

Mind like a diamond
Knows what's best
Shoes that cut                                                                                                                                                                                    
Eyes that burn like cigarettes
The right allocations
Fast                                                                                                                                                                                              
Thorough
Sharp as a tack
Playing with her jewellry
Putting up her hair
Touring the facilities                                                                                                                                                                            
Picking up slack
Short skirt
Long jacket                                                                                                                                                                                       
Gets up early
Stays up late
Uninterrupted prosperity
Uses a machete to cut through red tape
Fingernails that shine like justice
Voice that is dark like tinted glass
Smooth liquidation
Right dividends
Wants a car with a cupholder arm rest
Wants a car that will get her there
Changing her name from Kitty to Karen
Trading her MG for a white Chrysler LeBaron

They're not going to change any time soon, but I will want to do the following things with them:

  • Read them from and write them to a JSON file.
  • Associate a boolean with each attribute (bonus points for a way to associate any one arbitrary type).
  • Easily display these strings to a human.
  • Easily count how many are "set" (That is, a function that, when called on someone who gets up early, has the right dividends, and is sharp as a tack, but nothing else, returns 3).
  • Should be as strongly typed as possible (It should be impossible, or at least difficult, to ask for an attribute that doesn't exist. You should be able to see all the attributes by looking at the code).
  • Preserving this order would be a plus, but not strictly necessary.

The approaches I've thought of so far are:

  • A struct with all of these as fields, but the count function is inelegant to write, and the 'nice' string name of the fields has to be stored elsewhere. Even if that can be solved with tags, the count problem remains.

  • A map with constant keys (or an array with enumerated values). Counting is a simple loop, and the keys can be the nice string names. However, this creates the problem of asking for keys that don't exist, and you have to hide the dictionary behind a function to stop users from trying to add new keys.

Is there something I'm missing here, or will I have to compromise?

I'd use a uint64 as a bitset (or an actual bitset type, of which none are built in but some are open source). It meets your requirements in the following ways:

  • JSON storage as "010101" string or base64 (11 chars).
  • Easy display: just define an array of the strings in the same order they are stored in the bitset.
  • Easily count how many are "set" - use "popcount" (open source implementations are easy to come by).
  • Order is naturally preserved--the first attribute will always be bit 0, etc.

If you have more than 64 attributes, you can use math/big.

You can use map[int]interface{} to store the value of any length inside the interface with integer as key or you can also use slice of interface for looping inside the data like this []interface{}. Later on you can easily type assert the interface to get underlying value which is string in your case. Since it will be slice of interface or map of interface you can easily marshal it to convert it into json and save into file which can be read or write easily.