Saturday, May 9, 2015

Golang Maps with Examples for Beginners

Go provides built-in collection types like Slices & Maps. Maps are un-ordered collection of key-value pairs. In other 
languages a Map is known with names such as dictionaries, hash table, associative array etc. In the adjoining image here, we have a table that stores Key and Value pair


What are the values for key B?

  
By looking at the above image (table) you can easily derive that there are two set of values Name & Example. For key B the corresponding values are Name = Blue & Example = Sky. In a Map, values (data) can be retrieved very fast by providing the corresponding key.

At the end of this post we'll see how we can represent the above image (table) with the help of a Map.


Declare a Map
var color map[string]string

This should be read as the variable color is a map of string keys to string values.

A Map declaration should follow the below format:

var <name-of-the map> map[keyDataType]ValueDataType

Where as keyDataType = string, int, float. [i.e. Types where == operation works]

Initialize a Map
color := make(map[string]string)

Use of make function ensures that memory is allocated for the Map named color as Maps are Reference Types.

The above looks similar to simple Arrays with a little difference that Maps are dynamic in nature i.e. new items can be added to it. Another difference is that unlike Arrays which are sequential, Maps are NOT sequential.

The above declaration is rewritten below with an added second argument that defines initial capacity of the Map. In below declaration 3 is the initial capacity (Size) of the Map named color
                               color := make(map[string]string, 3)
Gopher Tip

The capacity of a map doesn't have to be known at creation. But for performance reasons, it is a good practice to specify the capacity even if it's an approximate number.

Remember: Maps are reference types. Note: The Gopher Tip image is an adaptation of Renee French's Go Gopher Mascot

Example Code

Here's a simple code example of Go Maps:

Code Snippet RefCode# Map 1.1
package main
import "fmt"
func main() {    
color := make(map[string]string)    

 color["R"] = "Red"    
 color["B"] = "Blue"   
 color["G"] = "Green"    

 fmt.Println(color["B"])
} 

Play with the above code here.
Output RefCode# Map 1.1
Blue
OK. That was quite simple. Now, let us modify the above code to get the user's favorite color as an input.
Code Snippet RefCode# Map 1.2
package main
import "fmt"
func main() {    
color := make(map[string]string)    

 color["R"] = "Red"    
 color["B"] = "Blue"   
 color["G"] = "Green"    

 fmt.Println("Select a Primary Color: R / B / G")
 var colorCode string
 fmt.Scanf("%s", &colorCode)
 
 if value, isOK := color[colorCode]; isOK {
 fmt.Println("You love " +value) } else {
    fmt.Println("Invalid entry OR Key not found in our record")
   }
} 


Code Explanation RefCode# Map 1.2

Here Scanf function from the fmt package is used to read the user's input.

We can see from RefCode# Map 1.2 that  only 3 key-value pairs: R, B, G (case sensitive) are present in the Map. 
  • What happens if a user enters any other key except R,B or G? 
  • How to check the existence of a a key?
This check is performed using the following construct, with 2 variables, namel value and isOK:

if value, isOK := color[colorCode]; isOK {

             //some code
}

isOK returns a Boolean value true only if the key is present in the Map else it returns false

The other variable value contains the actual value/data of the corresponding key of the Map.
As shown in the below output image, if after executing the above code I enter the key as R: It returns You love Red If you enter g as key; isOK will return false as we don't have any value corresponding to the key g (case sensitive).  G will retrieve a valid data as shown below.
Play with the RefCode# Map 1.2
Output RefCode# Map 1.2
Here's a succinct way to rewrite the code snippet RefCode# Map 1.2
Code Snippet RefCode# Map 1.3
package main
import "fmt"
func main() {    
color := map[string]string{    

        "R": "Red",  //Did you notice the comma?
        "B": "Blue",   
        "G": "Green",    
}
 fmt.Println("Select a Primary Color: R / B / G")
 var colorCode string
 fmt.Scanf("%s", &colorCode)
 
 if _, isOK := color[colorCode]; isOK {
 fmt.Println("You love " +color[colorCode]) } else {
    fmt.Println("Invalid entry OR Key not found in our record")
   }
}

Let us see an example of a Map where we have more than one named values/data for a single key.

Code Snippet RefCode# Map 1.4

1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
package main
import "fmt"
func main() {    
color := map[string]map[string]string{    

        "R": map[string]string{
           "name":"Red",  //Note the double quote in name, value
           "example":"Cherry",
        },
           
        "B": map[string]string{
           "name":"Blue",  
           "example":"Sky",
        }, 
        
       "G": map[string]string{
           "name":"Green",  
           "example":"Grass",
        },    
}
     fmt.Println("Select a Primary Color: R / B / G")
     var colorCode string
     fmt.Scanf("%s", &colorCode)
 
     if value, isOK := color[colorCode]; isOK {
       fmt.Println("You love " +value["name"] +" "+ value["example"]) 
     } else {
          fmt.Println("Invalid entry OR Key not found in our record")
     }
}
Output RefCode# Map 1.4
You can play with Code Snippet RefCode# Map 1.4

Please share if you liked it.

No comments:

Post a Comment