So generally you store []string
values for string
keys. Most of the time. And once in a while you'd like to store a map[string][]string
value for a string
key.
First, drop the pointer from the map type: maps are already small descriptors, you can pass maps which will pass a copy of the descriptor and not the whole content, and if you add a new key-value pair to the copy, you will see that in the original. Passing a map by value is efficient and has the desired effect / working.
To be precise: map types are actually pointers to a map descriptor under the hood, but this is an implementation detail, you don't need to know this to use / work with maps. Only thing that matters is you can pass around map values efficiently.
Keeping only one map and being able to store values of both type []string
and map[string][]string
would require you to change the value type to interface{}
, but then this would require you to use Type assertion every time you access an element in the params map, something like:
params := map[string]interface{}{}
params["a"] = []string{"b", "c"}
if list, ok := params["a"].([]string); ok {
fmt.Println(list)
}
Of course you could create a new type with map[string]interface{}
being its underlying type, and add Get()
and Set()
methods for the most common value type []string
, but instead I recommend a wrapper struct
for the params, with multiple maps in multiple fields:
type Params struct {
P map[string][]string
M map[string]map[string][]string
}
Your code may use the map whichever has the value type that suits the value to be stored, for example:
params2 := Params{map[string][]string{}, map[string]map[string][]string{}}
params2.P["a"] = []string{"b", "c"}
params2.M["B"] = map[string][]string{
"x": []string{"X", "Y"},
}
fmt.Println(params2.P["a"])
fmt.Println(params2.M["B"])
You may also add Get()
and Set()
methods to Params
that get and set elements from the most frequently used Params.P
map.
Try it on the Go Playground.