I'm new working on golang, In this case I have a map [string] which has a struct. At this point everything is works.
But I would like to have a map[string] in which I can access at the same time to another map[string] which has it self struct.
This is the code in which I'm trying to work.
type myStruct struct{
atrib1 string
atrib2 string
}
var apiRequest map[string] map[string]myStruct
I would like acces to something like this:
func main() {
apiRequest = make(map[string] map[string]myStruct)
apiKeyTypeRequest["Key"]["MyFirstOption"].atrib1 = "first Value first op"
apiKeyTypeRequest["Key"]["MyFirstOption"].atrib2 = "second Value first op"
apiKeyTypeRequest["Key"]["MysecondtOption"].atrib1 = "first Value second op"
}
An alternative to using a map inside a map, is to have a single map[mapKey]
where mapKey
is a struct:
type mapKey struct {
Key string
Option string
}
The benefits is that you only have to do a single lookup when searching for a myStruct
, and you only have to create a single map.
The downside is in case you need to be able to get that options map[string]myStruct
map, since it does not exist. Also, you cannot check if a certain key exists or not, because keys and options exists in pairs.
Working example:
package main
import "fmt"
type myStruct struct {
atrib1 string
atrib2 string
}
type mapKey struct {
Key string
Option string
}
func main() {
apiKeyTypeRequest := make(map[mapKey]myStruct)
apiKeyTypeRequest[mapKey{"Key", "MyFirstOption"}] = myStruct{"first Value first op", "second Value first op"}
apiKeyTypeRequest[mapKey{"Key", "MysecondtOption"}] = myStruct{atrib1: "first Value second op"}
fmt.Printf("%+v
", apiKeyTypeRequest)
}
Playground: http://play.golang.org/p/tGd7ja7QI2
As @FUZxxl has said, you need to initialize the sub-map for each outer map, but there is a shorthand syntax for it:
type myStruct struct {
atrib1 string
atrib2 string
}
func main() {
var myMap = map[string]map[string]myStruct{
"foo": {
"bar": {attrib1: "a", attrib2: "b"},
"baz": {"c", "d"}, //or by order...
},
"bar": {
"gaz": {"e", "f"},
"faz": {"g", "h"},
},
}
fmt.Println(myMap["foo"]["bar"].atrib1)
fmt.Println(myMap["bar"]["gaz"].atrib2)
}
To expand upon previous answers, each map must be declared and instantiated (as well as the struct at the end of the map), that means you'll need to instantiate the "outer" map
mapOfMaps := make(map[string]map[string]myStruct)
as well as the "inner" map(s) for each key you have.
mapOfMaps[key] = make(map[string]myStruct)
The obvious issue you run into here is how do you dynamically check to see if the mapOfMaps[key]
has already been instantiated? You do this using the following syntax:
if _, ok := mapOfMaps[key]; !ok {
mapOfMaps[key] = make(map[string]myStruct)
}
This syntax checks to see if mapOfMaps
already has an instantiated value for that key, and if not instantiates it. Similarly, you can use the same syntax to instantiate the structs you are using by checking to see of mapOfMaps[key][key2]
has been instantiated yet.
if _, ok := mapOfMaps[key][key2]; !ok {
mapOfMaps[key][key2] = new(myStruct)
}
Now you can access the struct through the call to 2 keys and an attribute of the struct
fmt.Println(mapOfMaps[key][key2].atrib1)