Tuesday, November 27, 2018

Learn Golang tutorials - Map Guide with examples

In this tutorial, We are going to learn map built-in type with examples in the Go Language.
Learn Golang tutorials - Map Guide with examples

Golang Map Introduction

A map is a popular collection data structure, contains key and value pairs.  It is used to represent hashtable and dictionaries in other programming languages.
Java has HashTable, Python has Dictionary types. It provides fast loops, search, update, deletions based on the keys.
Important points of Maps in Go Programming language.
  • It is BuiltIn type in Golang
  • It is an unordered data structure, which contains key and value pairs
  • A map does not allow duplicate keys but can have duplicate values
  • The keys in the map are unique, values need not required
  • This is also called associative arrays, hashmaps or dictionaries in other programming languages
  • Key type is of only comparable types - functions, maps, slices are not allowed
  • a value type is of any type - Primitive types, Custom Types or interface{} types

Syntax 

var variablename map[keytype]valuetype
the syntax contains below things

Start a var keyword used to declare a variable of map type. variablename is a name of the variable name of a map.It should be the valid identifier. a map is the keyword used followed by key type declared in square brackets and value type.

Variable Declaration and initialized a map

We will see various ways of creating and initializing a map

zero value map with nil type

This map is just declared not initialized and this is called zero value map. zero value map value is nil. It has no key and values. Following is a Map variable declaration with string keys and int values. variable k is of map type with assigning string values to integer.
// keys are of string type, values are of int type
var k map[string]int; // map is nil value
Map types are reference types like slices. value of k is nill and not pointed initialized map Following is an example
package main
import (
 "fmt"
)
func main() {
 var mymap map[string]int
 fmt.Println(mymap)
 if mymap == nil {
  fmt.Println("map is nil")
 }

}
Output is
map[]
map is nil
when you add values to nil map, It gives runtime error - panic: assignment to entry in nil map. A map should be always initialized to add elements to it following is an example for adding elements to map
package main

import (
 "fmt"
)

func main() {
 var mymap map[string]int
 fmt.Println(mymap)
 if mymap == nil {
  fmt.Println("map is nil")
 }
 mymap["kiran"] = 1 // this gives runtime error
}
output is
map[]
map is nil
panic: assignment to entry in nil map

goroutine 1 [running]:
main.main()
        A:/Golang/work/Test.go:13 +0xd3
exit status 2

Create Map using inbuilt make function 

You can create a map using in-builtin make() function. make function allocates hashmap data structure, returns a map that references to it. This make function accepts the type of the map and capacity. This creates a map and initized with empty elements.
Here is an syntax of make fucntion
make(map[keytype]valuetype, optional capacity)
This function accepts the type of the map and optional initial capacity, overrides default capacity For example
var mymap=make(map[string]int)
1:= make(map[string]int, 20)
the above code creates a named map - mymap which accepts key of strings and values of int type. This is called Empty Map. nil map works same as an empty map when reading elements. When attempting to add elements to Nil Map throws panic runtime. Empty Map works as expected when adding elements The above line code can be rewritten using short hand variable declaration using shorthand assignment operator (:=).
following is new syntax
mymap:=make(map[string]int)
following is an example for make function
package main

import (
 "fmt"
)

func main() {
 var mymap = make(map[string]int)
 fmt.Println(mymap)
 if mymap == nil {
  fmt.Println("map is nil")
 } else {
  fmt.Println("map is not nil")

 }
 mymap["kiran"] = 1 // map is initilzed, can add elements to it
 fmt.Println(mymap)

}
Output is
map[]
map is not nil
map[kiran:1]

Create and initializing using map literals 

 A map can also be created using map literals with initial key and values. For example, Let us create an empty map. This creates a empty map is equivalent to make(map[string]int) function
var mymap = map[string]int{} 
This creates an initialized empty map and ready to accept the values to be added Following is an example for initial data filled. This will be created by passing key and values separated with colon inside curly braces {}
var mymap = map[string]int{
 "Kiran": 1,
 "John": 2,
 "Frank": 3, // comma is required 
}
last trailing comma of map literals is required, if comma omitted, It throws compilation error - syntax error: unexpected newline, expecting comma or } Follow is a complete example
package main

import (
 "fmt"
)

func main() {
 var mymap1 = map[string]int{} // Create and initialize Empty Map
 fmt.Println(mymap1)
 // Create and initialize iniitial data using map literal 
 var mymap = map[string]int{
  "Kiran": 1,
  "John":  2,
  "Frank": 3,
 }
 fmt.Println(mymap)

}
Output is
map[]
map[Kiran:1 John:2 Frank:3]

Adding elements (key-value pair) to a Map 

Once the map is created, you can add elements to the map using the following syntax. This syntax is similar to arrays and slices in Golang.
mapvariable[key]=value
The above line of code sets the key to the value of a map. if you try to add a key that already exists, it updates its value to new value
package main

import (
 "fmt"
)

func main() {
 // Create a map
 var employees = make(map[int]string)

 // Adding elements to a map
 employees[1] = "kiran"
 employees[2] = "Frank"
 employees[3] = "John"

 fmt.Println(employees)
 /*
    This overrides its value when key already exists in a map
 */
 employees[1] = "Ram"
 fmt.Println(employees)

}
Output is
map[1:kiran 2:Frank 3:John]
map[1:Ram 2:Frank 3:John]
Above examples create and initializes using make)() function and add some elements. if a key already exists, It overrides its value. Get items or value with given key in a map You can retrieve values based on key using following syntax
value := mapvariable[ key ]
This retrieves value if the map contains key, if not it returns non zero value of map value types(0 for int,"" for strings,0.0 for float types).
Following is the example accessing items of a map
package main

import (
 "fmt"
)

func main() {
 // Create a map
 var employees = make(map[int]string)

 // Adding elements to a map
 employees[1] = "kiran"
 employees[2] = "Frank"
 employees[3] = "John"

 fmt.Println(employees)
 var name = employees[1]
 fmt.Println("Key exist case ", name)
 name1 := employees[11]
 fmt.Println("Key not exist case: ", name1)
}
Output is
map[1:kiran 2:Frank 3:John]
Key exist case  kiran
Key not exist case:
In the above program, key=1 already exists in a map, corresponding value=kiran is returned. key=2 does not exist in a map, we get zero value of map value type, here map value type is a string, the empty string "" is returned.
how do we find whether a key exists or not in a map? we can differentiate between empty values and non-existing keys using two value assignment map retrieval syntax.

Check if the map contains a key 

Go lang provides two value assignment syntax for retrieving values. with map[key] syntax, It provides extra boolean flag - true, if exists in a map, false - key not exists in a map
value, ok := map[key]  
ok is a boolean value - true if a key exists, false - not exists Complete example for checking key exists in a map
package main

import (
 "fmt"
)

func main() {
 // Create a map
 var employees = make(map[int]string)

 // Adding elements to a map
 employees[1] = "kiran"
 employees[2] = "Frank"
 employees[3] = "John"

 fmt.Println(employees)
 name, flag := employees[1]
 fmt.Printf("key:1 value: %s flag: %v\n", name, flag)
 name1, flag := employees[11]
 fmt.Printf("key:11 value: %s flag: %v\n", name1, flag)
}
The output of the above code is
map[1:kiran 2:Frank 3:John]
key:1 value: kiran flag: true
key:11 value:  flag: false
the above example, retrieving key=1 that exists in a map and returned value=kiran and ok=true retrieving key=11 that key does not exist in a map, returned value type zero value ie value="" and ok=false.
you can use blank identifier(_) in place of value to omit value field

Size of a map - BuiltIn len() function 

You can count the number of items or keys in a map using built-in len() function Syntax is as follows
len(map)
len() function returns the number of items in a map nil or empty map always return zero. here is an example for the length of a map
package main

import (
 "fmt"
)

func main() {
 // Create a map
 var employees = make(map[int]string) // nil map
 fmt.Println(employees)
 fmt.Println("Size: ", len(employees))

 // Adding elements to a map
 employees[1] = "kiran"
 employees[2] = "Frank"
 employees[3] = "John"

 fmt.Println(employees)
 fmt.Println("Size: ", len(employees))

}
Output is
map[]
Size:  0
map[1:kiran 2:Frank 3:John]
Size:  3

remove items from a map - built-in delete function

Built-in delete function() is used to delete an item from a map. Following is the syntax for this function
delete(map,key)
This function deletes the item with the given key. It does not return any value if the key does not exist in a map.
package main

import (
 "fmt"
)

func main() {
 // Create a map using map literal
 employees := map[int]string{
  1: "ram",
  2: "arun",
  3: "Gef",
 }

 fmt.Println(employees)
 fmt.Println("Size: ", len(employees))
 delete(employees, 1)
 fmt.Println(employees)
 fmt.Println("Size: ", len(employees))

}
The above code delete key=1 from map and output is as follows
map[1:ram 2:arun 3:Gef]
Size:  3
map[2:arun 3:Gef]
Size:  2

Iterate over all items of the map - range form of for loops

 Map items are iterated using for loop with range keyword. It returns key and values for each iteration item. if an entry is added or removed which is not iterated during iteration, The corresponding item will not be considered
package main

import (
 "fmt"
)

func main() {
 // Create a map using map literal
 employees := map[int]string{
  1: "ram",
  2: "arun",
  3: "Gef",
 }
 for key, value := range employees {
  fmt.Println(key, value)

 }

}
Since the map is an unordered data structure, Order is not guaranteed. when you run the above program multiple output order might change.
1 ram
2 arun
3 Gef

Copy map

The below talks about copying map using reference and values

map copy is reference types 

Maps are reference type like slices meaning is map is just reference point to allocated data structure data. When a map is assigned to the new map, both maps points to the same data structure. if any changes in one map will reflect in other maps This is helpful when map is passed to the function, any changes in the function, function caller reflect the changes in a map
package main

import (
 "fmt"
)

func main() {
 // Create a map using map literal
 employees := map[int]string{
  1: "ram",
  2: "arun",
  3: "Gef",
 }
 employees[4] = "jack"
 fmt.Println("original map: ", employees)
 newEmployees := employees
 newEmployees[4] = "herald"
 fmt.Println("new  map: ", employees)

}
in the above program, original map is assigned to new map, In the next line, changed 4=jack to 4=herald in new map. This is reflected in the original map And the output is copied
original map:  map[1:ram 2:arun 3:Gef 4:jack]
new  map:  map[2:arun 3:Gef 4:herald 1:ram]

values of a map

In golang, when the map is assigned or passed to function, it is a copy of reference not underline data stored. How do we copy map data? The below program copy the map data to another map

package main

import (
 "fmt"
)

func main() {
 // Create a map using map literal
 source := map[int]string{
  1: "ram",
  2: "arun",
  3: "Gef",
 }
 destination := make(map[int]string)
 fmt.Println("source: ", source)
 for key, value := range source {
  destination[key] = value
 }
 fmt.Println("destination: ", destination)
}
An output of the above program is

source:  map[2:arun 3:Gef 1:ram]
destination:  map[1:ram 2:arun 3:Gef]

Check Compare equivalence of map 

== is used to check map value for nil values. It cannot be useful for equality of maps To compare two maps are equal or not, We will write a code or use reflect.DeepEqual() function reflect.DeepEqual() function checks sizes and each item are equal
package main

import (
 "fmt"
 "reflect"
)

func main() {
 // Create a map using map literal
 source := map[int]string{
  1: "ram",
  2: "arun",
  3: "Gef",
 }
 destination := map[int]string{
  1: "ram",
  2: "arun",
  3: "Gef",
 }
 fmt.Println("source: ", source)
 fmt.Println("destination: ", destination)
 eq := reflect.DeepEqual(source, destination)
 if eq {
  fmt.Println("Maps are equal.")
 } else {
  fmt.Println("Maps are not unequal.")
 }

}
Output is
source:  map[2:arun 3:Gef 1:ram]
destination:  map[1:ram1 2:arun 3:Gef]
Maps are not unequal.

Convert map key/values into slice example 

The below example code creates a slice for key and values of the map.
The map is iterated using for loop with range form. For each iteration, key or value is added to the corresponding slices.
package main

import (
 "fmt"
)

func main() {
 // Create a map using map literal
 mymap := map[int]string{
  1: "ram",
  2: "arun",
  3: "Gef",
 }
 // convert map keys into slice
 keySlice := make([]int, 0, len(mymap))
 for k := range mymap {
  keySlice = append(keySlice, k)
 }
 fmt.Println(keySlice)
 // convert map values into slice
 valueSlice := make([]string, 0, len(mymap))
 for _, value := range mymap {
  valueSlice = append(valueSlice, value)
 }
 fmt.Println(valueSlice)
}
An output of the above program is
[2 3 1]
[ram arun Gef]

Related article


EmoticonEmoticon