This is the 10th day of my participation in Gwen Challenge

Hi, I’m @Luo Zhu

This article was first published on luo Zhu’s official website

This article was translated from Golang Tutorial Series

This article synchronizes in the public account “luo Zhu early teahouse”, reprint please contact the author.

Creation is not easy, form a habit, quality three even!

What is a map?

Map is a built-in type in Go for storing key-value pairs. Let’s take a startup with a few employees. For simplicity, let’s assume that all of these employee names are unique. We are looking for a data structure to store each employee’s salary. For this use case, a map would be a perfect choice. The employee’s name can be a key, and the salary can be a value. Maps are similar to dictionaries in other languages, such as Python.

How to create a Map

You create a map by passing key and value types to the make function. Here is the syntax for creating a new map.

make(map[type of key]type of value)
Copy the code
employeeSalary := make(map[string]int)
Copy the code

The above line creates a map named employeeSalary with a String key and an int value.

package main

import (
    "fmt"
)

func main(a) {
    employeeSalary := make(map[string]int)
    fmt.Println(employeeSalary)
}
Copy the code

Run in Playground

The above program creates a map named employeeSalary with a string key and an int value. The above program will print.

map[]
Copy the code

Since we did not add any elements to the map, it is empty.

Add elements to map

The syntax for adding new elements to a map is the same as the syntax for an array. The following program adds some new employees to the employeeSalary Map.

package main

import (
    "fmt"
)

func main(a) {
    employeeSalary := make(map[string]int)
    employeeSalary["steve"] = 12000
    employeeSalary["jamie"] = 15000
    employeeSalary["mike"] = 9000
    fmt.Println("employeeSalary map contents:", employeeSalary)
}
Copy the code

Run in playground

We’ve added three employees — Steve, Jamie and Mike — and their corresponding salaries.

The above program prints out.

employeeSalary map contents: map[steve:12000 jamie:15000 mike:9000]
Copy the code

You can also initialize a map in the declaration itself.

package main

import (
    "fmt"
)

func main(a) {
    employeeSalary := map[string]int {
        "steve": 12000."jamie": 15000,
    }
    employeeSalary["mike"] = 9000
    fmt.Println("employeeSalary map contents:", employeeSalary)
}
Copy the code

Run in playground

The above program declares the employeeSalary and adds two elements to the declaration itself. Later, an element with a key of Mike was added. The program prints out

employeeSalary map contents: map[jamie:15000 mike:9000 steve:12000]
Copy the code

It doesn’t have to be a string type to be a key. All comparable types such as Booleans, integers, floating-point, complex numbers, and strings can also be keys. Even user-defined types such as structures can be keys. If you want to learn more about comparative types, visit golang.org/ref/spec#Co…

The map of zero value

The zero value of map is nil. If you try to add elements to a nil map, a runtime panic will occur. Therefore, before adding elements, the map must be initialized.

package main

func main(a) {
    var employeeSalary map[string]int
    employeeSalary["steve"] = 12000
}
Copy the code

Run in playground

In the above program, employeeSalary is nil, and we try to add a new key to the map. The program will have an error

panic: assignment to entry in nil map

Retrieves a key value from the map

Now that we have added some elements to the map, let’s learn how to retrieve them. Map [key] is the syntax for retrieving map elements.

package main

import (
    "fmt"
)

func main(a) {
    employeeSalary := map[string]int{
        "steve": 12000."jamie": 15000."mike": 9000,
    }
    employee := "jamie"
    salary := employeeSalary[employee]
    fmt.Println("Salary of", employee, "is", salary)
}
Copy the code

Run in playground

The above procedure is very straightforward. Employee Jamie’s salary is retrieved and printed. The program prints

Salary of jamie is 15000
Copy the code

What happens if an element doesn’t exist? Map will return a zero value for the element’s type. In the example of the employeeSalary map, if we attempt to access an element that does not exist, we return the zero value of int, that is, 0.

package main

import (
    "fmt"
)

func main(a) {
    employeeSalary := map[string]int{
        "steve": 12000."jamie": 15000,
    }
    fmt.Println("Salary of joe is", employeeSalary["joe"])}Copy the code

Run in playground

The output of the above program is

Salary of joe is 0
Copy the code

The above program returns Joe’s salary as 0. There will be no runtime error when we try to retrieve the value of a key that does not exist in the map.

Checking if a key exists

In the previous section, we learned that when a key does not exist, a zero value of that type is returned. This does not help when we want to know if the key really exists in the map.

For example, we want to know if a key exists in the employeeSalary Map.

value, ok := map[key]
Copy the code

This is the syntax for finding out if a particular key exists in the map. If OK is true, the key exists and its value is in the variable value, otherwise it does not exist.

package main

import (
    "fmt"
)

func main(a) {
    employeeSalary := map[string]int{
        "steve": 12000."jamie": 15000,
    }
    newEmp := "joe"
    value, ok := employeeSalary[newEmp]
    if ok == true {
        fmt.Println("Salary of", newEmp, "is", value)
        return
    }
    fmt.Println(newEmp, "not found")}Copy the code

Run in playground

In the above program, OK will be false because Joe does not exist. Therefore, the program will print.

joe not found
Copy the code

Iterate over all the elements in a map

The range form of the for loop is used to traverse all elements of a map.

package main

import (
    "fmt"
)

func main(a) {
    employeeSalary := map[string]int{
        "steve": 12000."jamie": 15000."mike":  9000,
    }
    fmt.Println("Contents of the map")
    for key, value := range employeeSalary {
        fmt.Printf("employeeSalary[%s] = %dn", key, value)
    }

}
Copy the code

Run in playground

The output of the above program.

Contents of the map
employeeSalary[mike] = 9000
employeeSalary[steve] = 12000
employeeSalary[jamie] = 15000
Copy the code

An important fact is that when using for range, the order in which values are retrieved from the map is not guaranteed to be the same in each execution of the program. It is also different from the order in which elements are added to the map

Removes elements from the map

Delete (map, key) is the syntax for deleting a key from a map. The delete function does not return any value.

package main

import (
    "fmt"
)

func main(a) {
    employeeSalary := map[string]int{
        "steve": 12000."jamie": 15000."mike": 9000,
    }
    fmt.Println("map before deletion", employeeSalary)
    delete(employeeSalary, "steve")
    fmt.Println("map after deletion", employeeSalary)

}
Copy the code

Run in playground

The above program removes the key Steve and prints it

map before deletion map[steve:12000 jamie:15000 mike:9000]
map after deletion map[mike:9000 jamie:15000]
Copy the code

If we try to remove a key that does not exist in the map, there will be no runtime error.

Structure map

So far, we’ve only stored employees’ salaries on the map. Wouldn’t it be great if we could also store every employee’s country on the map? This can be done by using a structure map. Employees can be represented as a structure containing salary and country fields, which are stored in the Map as string keys and structure values. Let’s write a program to see how to do this.

package main

import (
    "fmt"
)

type employee struct {
    salary  int
    country string
}

func main(a) {
    emp1 := employee{
        salary:  12000,
        country: "USA",
    }
    emp2 := employee{
        salary:  14000,
        country: "Canada",
    }
    emp3 := employee{
        salary:  13000,
        country: "India",
    }
    employeeInfo := map[string]employee{
        "Steve": emp1,
        "Jamie": emp2,
        "Mike":  emp3,
    }

    for name, info := range employeeInfo {
        fmt.Printf("Employee: %s Salary:$%d Country: %s\n", name, info.salary, info.country)
    }

}
Copy the code

Run in playground

In the above program, the Employee structure contains salary and country fields. We created three employees emp1, emp2, and emp3.

We initialize a map of key type String and value type Employee with the three employees we created.

This program will print.

Employee: Mike Salary:$13000  Country: India
Employee: Steve Salary:$12000  Country: USA
Employee: Jamie Salary:$14000  Country: Canada
Copy the code

The length of the map

The length of a map can be determined using the len function.

package main

import (
    "fmt"
)

func main(a) {
    employeeSalary := map[string]int{
        "steve": 12000."jamie": 15000,
    }
    fmt.Println("length is".len(employeeSalary))

}
Copy the code

Run in playground

Len (employeeSalary) in the above program returns the map length. The above program prints out.

length is 2
Copy the code

Map is a reference type

Like slices, a map is a reference type. When a map is assigned to a new variable, they all point to the same internal data structure. Thus, changes in one will be reflected in the other.

package main

import (
    "fmt"
)

func main(a) {
    employeeSalary := map[string]int{
        "steve": 12000."jamie": 15000."mike": 9000,
    }
    fmt.Println("Original employee salary", employeeSalary)
    modified := employeeSalary
    modified["mike"] = 18000
    fmt.Println("Employee salary changed", employeeSalary)

}
Copy the code

Run in playground

In the above program, employeeSalary is assigned to Modified. In the next line, Mike’s salary is changed to 18000 in the Modified Map. Mike’s salary is now 18,000 in employeeSalary. The program output.

Original employee salary map[jamie:15000 mike:9000 steve:12000]
Employee salary changed map[jamie:15000 mike:18000 steve:12000]
Copy the code

The same is true when a map is passed to a function as an argument. When any changes are made to the map in a function, it is also visible to the caller.

The map equality

Maps cannot be compared using the == operator. == can only be used to check if a map is nil.

package main

func main(a) {
    map1 := map[string]int{
        "one": 1."two": 2,
    }

    map2 := map1

    if map1 == map2 {
    }
}
Copy the code

Run in playground

The above program will not compile with an error

invalid operation: map1 == map2 (map can only be compared to nil)
Copy the code

One way to check if two maps are equal is to compare each element of each map one by one. Another approach is to use reflection. I encourage you to write a program for this and make it work.

I’ve put together a program of all the concepts we’ve discussed. You can download it from Github.

This concludes the tutorial. I hope you like it. Please leave a comment.