Creating Maps in GoLang: Step-by-Step Tutorial | DistantJob - Remote Recruitment Agency
Tech Insights

GoLang Map Tutorial: A Step-by-Step Guide to Creating Maps in GoLang

Joana Almeida
Software Developer - - - 3 min. to read

Maps are a very powerful and versatile tool for any programmer in any language. GoLang is no exception.

If you want to know how to use this specific data structure in GoLang, you can use the following 6 simple steps to learn how to create and manipulate maps in your own GoLang projects.

But first, let’s go over what maps are and how they are used.

Understanding GoLang Maps: An Overview

A Map in GoLang is a data structure that allows you to store data indexed by a unique key. It is an efficient way to store and retrieve data that needs to have an unique identifier.

This functionality shines in real-world scenarios where data needs to be quickly accessed, updated, or managed based on unique identifiers, like managing a database of customer records where each customer has a unique ID. Compared to other data structures like arrays or slices, GoLang Maps offers a speedier look-up for values based on keys, which is a significant advantage.

While the idea of Maps isn’t unique to GoLang and is shared across various programming languages like Python or Java, the implementation and syntax may exhibit variances. For instance, the basic syntax of a GoLang Map is map[KeyType]ValueType, representing the type of keys (KeyType) and the type of values (ValueType) the map will hold. This simple yet powerful structure forms the crux of many data management operations in GoLang, making it a vital concept to grasp in this GoLang tutorial.

As we delve deeper into the next sections, you’ll learn the steps to create and manipulate GoLang Maps, unlocking the potential to handle data efficiently in your GoLang projects.

Hire a Golang Developer

6 Simple Steps to Create a GoLang Map

Creating and manipulating maps is actually quite simple. Let’s delve into this Golang tutorial where we’ll go over what you need to know in order to use them and how to create one.

Map Structure in GoLang

Maps are containers consisting of key-value pairs. The ‘key’ is used as an indexer for the rest of the data, or our ‘value’.

The advantage of a map is that the keys do not have to be sequential and can be inserted in any order. When any key is inserted, the map internally takes care of indexing it in a way that makes future searches fast and efficient.

1. Initializing a Map

Before using a map, you have to initialize it. There are two main ways to do this.

Method 1: Declare and Make

make() is a built-in function of Go that is used to allocate and initialize a complex data structure, such as a map. If you try to use a map before ‘making’ it, an error will occur.

This method declares the map variable, and the map has no entries.

Declare and then make
var map_name map[key_type]value_type

    // Any number of lines of code can go here, but you must not use 'map_name' in them

    map_name = make(map[kay_type]value_type)

This is useful in case you need to declare the map before allocating and initializing it in some later part of your code.

Declare and make in the same line

var map_name = make(map[key_type]value_type)

Or you can use the short variable declaration operator (‘:=’).

map_name := make(map[key_type]value_type)

The map becomes immediately available to be manipulated further.

Method 2: Declare and Initialize

In this case, the map is declared and immediately filled with any number of entries you require.

 map_name := map[key_type]value_type{
        key1: value1,
        key2: value2, // remember to always use a comma, even in the last key-value pair
    }

Practical Example

We’ll be doing a practical example by developing a simple program that keeps track of the patrons of a library. We’ll be using a map to store our library’s patrons. Their Patron ID will be our ‘key’, and their name our ‘value’. The patron ID will be a simple integer, and their name a string.

Since we already want to have some patrons in our library, we’ll declare and initialize straight away.

Mr. Terrence and Ms. Evelyn work at the library and also use it, so they are our first patrons to be registered.

We’ll import the fmt package from now on so we can print our map’s contents to the screen.

Method 1

package main

import "fmt"

func main() {
    patrons := make(map[int]string)

    patrons[0] = "Terrence"
    patrons[1] = "Evelyn"

    fmt.Println(patrons)
}

The output is:

map[0:Terrence 1:Evelyn]

Method 2

package main

import "fmt"

func main() {
    patrons := map[int]string{
        0: "Terrence",
        1: "Evelyn",
    }

    fmt.Println(patrons)
}

The output is:

map[0:Terrence 1:Evelyn]

2. Adding to a Map

Adding to a map is simple. All you need to do is assign a value to a key on a map. Remember that keys are unique and cannot repeat. If the key already exists, the assignment will replace the existing value.

map_name[key] = value

Practical Example

New patrons are now registering in our library, so we’ll add them to our map and give them unique IDs.

package main

import "fmt"

func main() {
    patrons := map[int]string{
        0: "Terrence",
        1: "Evelyn",
    }

    patrons[2] = "Jonathan"
    patrons[3] = "Rick"

    fmt.Println(patrons)
}

The output is:

map[0:Terrence 1:Evelyn 2:Jonathan 3:Rick]

3. Retrieving a Value from a Golang Map

If you want to retrieve a value from a map, you do it using the key, like so:

map_name[key]

Practical Example

Let’s see who our patron 1 is.

package main

import "fmt"

func main() {
    patrons := map[int]string{
        0: "Terrence",
        1: "Evelyn",
    }

    fmt.Printf("Who is our Patron #%d? %s!", 1, patrons[1])
}

The output is:

Who is our Patron #1? Evelyn!

4. Iterating a Map

Iterating maps is usually done with a for loop combined with the range keyword.

for key, value := range map_name {
        // Process each key-value pair. You have access to both the 'key' and the 'value'.
    }

If you don’t care about a specific part of the key-value pair, you can use the blank identifier (‘_’) instead of declaring a variable.

  for _, value := range map_name {
        // Process each 'value' on the map. The key is automatically discarded.
    }
    
    for key, _ := range map_name {
        // Process each 'key' on the map. The value is automatically discarded.
    }

Practical Example

We’ve seen that you can print a whole map at once using fmt.Println(), but let’s format it a little better by ourselves, and also provide some more information about our data.

package main

import "fmt"

func main() {
    patrons := map[int]string{
        0: "Terrence",
        1: "Evelyn",
    }
	
    fmt.Printf("--- Our Patrons ---\n")
    for id, name := range patrons {
        fmt.Printf("ID: %d , Name: %s\n", id, name)
    }
		
    fmt.Printf("\n\n--- Used IDs ---\n")
    for id, _ := range patrons {
        fmt.Printf("%d, ", id)
    }
	
    fmt.Printf("\n\n--- Our Patrons' Names ---\n")
    for _, name := range patrons {
        fmt.Printf("%s, ", name)
    }    
}

The output is:

--- Our Patrons ---
ID: 0 , Name: Terrence
ID: 1 , Name: Evelyn

--- Used IDs ---
1, 0, 

--- Our Patrons' Names ---
Evelyn, Terrence, 

5. Checking if an entry exists on a Map

When we try to get a value from a map, it also returns a boolean that tells us if the key exists in the map or not. We can then use it to make checks and have code ready that is tailored to either scenario where the key exists or doesn’t.

 returned_value, boolean_exists := map_name[key]
    if(boolean_exists){
        // You can now use 'returned_value'
    }

If the value is irrelevant to what you want to do and you just want to check that the key exists on the map, you can use the blank identifier.

_, boolean_exists := map_name[key]
    if(boolean_exists){
        // You know that the key exists on the map, but not the associated value
    }

Practical Example

Let’s check our patrons and see if an ID is being used and if so, by whom.

package main

import "fmt"

func main() {
    patrons := map[int]string{
        0: "Terrence",
        1: "Evelyn",
    }
	
    patron1_name, patron1_exists := patrons[1]
    if(patron1_exists){
        fmt.Printf("Patron #%d exists and is named %s.\n", 1, patron1_name)
    } else {
        fmt.Printf("Patron #%d does not exist.\n", 1)
    }
	
    _, patron2_exists := patrons[2]
    if(patron2_exists){
        fmt.Printf("Patron #%d exists.\n", 2)
    } else {
        fmt.Printf("Patron #%d does not exist.\n", 2)
    }
}

The output is:

Patron #1 exists and is named Evelyn.
Patron #2 does not exist.

6. Removing an entry from a Golang Map

To remove a key-value pair on a map, all you need to do is use the built-in function delete().

delete(map_name, key)

Practical Example

Mr. Terrence is moving away and unfortunately will no longer be working at the library. As such, we need to remove him from our patrons.

package main

import "fmt"

func main() {
    patrons := map[int]string{
        0: "Terrence",
        1: "Evelyn",
    }

    fmt.Println("Before Mr. Terrence Leaves:")
    fmt.Println(patrons, "\n")

    delete(patrons, 0)

    fmt.Println("After Mr. Terrence Leaves:")
    fmt.Println(patrons, "\n")
}

The output is:

Before Mr. Terrence Leaves:
map[0:Terrence 1:Evelyn] 

After Mr. Terrence Leaves:
map[1:Evelyn] 

Remember: GoLang Maps are reference types

This is useful to remember if you’re assigning a map to another variable. Manipulating that new variable will also change the original map.

map_name := make(map[key_type]value_type)
    
    map_copy := map_name
    
    map_copy[key] = value

    // Both 'map_name' and 'map_copy' now have an entry [key:value]

Practical Example

Imagine we wanted to have separate dedicated lists for our patrons and our staff, but still include our staff as our patrons, since they also use the library.

package main

import "fmt"

func main() {
    staff := map[int]string{
        0: "Terrence",
        1: "Evelyn",
    }

    patrons := staff

    patrons [2] = "Jonathan"
    patrons [3] = "Rick"

    fmt.Println("Our Staff:")
    fmt.Println(staff, "\n")

    fmt.Println("Our Patrons:")
    fmt.Println(patrons, "\n")
}

The output is:

Our Staff:
map[0:Terrence 1:Evelyn 2:Jonathan 3:Rick] 

Our Patrons:
map[0:Terrence 1:Evelyn 2:Jonathan 3:Rick] 

This clearly would not work. We’d need to have two separate lists with repeat entries.

package main

import "fmt"

func main() {
    staff := map[int]string{
        0: "Terrence",
        1: "Evelyn",
    }
	
    patrons := make(map[int]string)

    patrons [0] = "Terrence"
    patrons [1] = "Evelyn"
    patrons [2] = "Jonathan"
    patrons [3] = "Rick"

    fmt.Println("Our Staff:")
    fmt.Println(staff, "\n")

    fmt.Println("Our Patrons:")
    fmt.Println(patrons, "\n")
}

The output is:

Our Staff:
map[0:Terrence 1:Evelyn] 

Our Patrons:
map[0:Terrence 1:Evelyn 2:Jonathan 3:Rick] 

Common Mistakes When Working with GoLang Maps and How to Avoid Them

Working with maps in GoLang can be straightforward once you grasp the basics, but there are common pitfalls that developers, especially those new to GoLang, may stumble upon. Here’s a roundup of some common mistakes and how you can sidestep them:

1. Not Initializing Maps Before Use:

GoLang maps need to be initialized before they can be used.

  • Solution: Always initialize your maps using the make function or a map literal.
go
// Correct way:
myMap := make(map[string]int)
// or
myMap := map[string]int{}

2. Assuming Order in Map Iteration:

Maps in GoLang do not maintain an order of elements. Assuming an order during iteration is a mistake.

  • Solution: If order is crucial, consider using a slice to maintain order or a sorted map implementation.
go
// If order is needed, use a slice:
keys := []string{}
for key := range myMap {
    keys = append(keys, key)
}
sort.Strings(keys)  // Now keys are sorted

3. Modifying Maps During Iteration:

Modifying a map while iterating over it can cause errors.

  • Solution: Collect the keys or values you want to modify in a separate slice, then iterate over that slice to make changes to the map.
go
// Collect keys:
keysToModify := []string{}
for key, value := range myMap {
    if value > 10 {
        keysToModify = append(keysToModify, key)
    }
}
// Modify map:
for _, key := range keysToModify {
    myMap[key] += 10
}

4. Ignoring the ok Check:

When accessing an element, it’s good practice to perform an ok check to see if the key exists in the map to avoid zero-value errors.

  • Solution: Always perform the ok check when accessing map elements.
go
// Correct way:
value, ok := myMap["someKey"]
if ok {
    // Key exists
} else {
    // Key does not exist
}

By being aware of these common missteps and applying the outlined solutions, you’ll be on a surer footing when working with GoLang maps, making your coding journey smoother and bug-free.

Conclusion

Maps are extremely versatile tools that help you index and search through data efficiently and easily. We hope we’ve given you a comprehensive primer on how Go Maps work and how you can use them in your projects.

Go is a very easy-to-use language that is growing rapidly in terms of usage by many high profile companies. If you’re looking to hire Go developers, DistantJob can help you find the perfect fit for your needs.

Joana Almeida

Joana Almeida (GitHub: SorceryStory) is our Technical Writer at DistantJob. With her unique background spanning software development and game design, Joana brings deep technical insights and clear communication to her writing on cutting-edge technologies, development frameworks, and collaboration tips and tools for remote dev teams.

Learn how to hire offshore people who outperform local hires

What if you could approach companies similar to yours, interview their top performers, and hire them for 50% of a North American salary?

Subscribe to our newsletter and get exclusive content and bloopers

or Share this post

Learn how to hire offshore people who outperform local hires

What if you could approach companies similar to yours, interview their top performers, and hire them for 50% of a North American salary?

Reduce Development Workload And Time With The Right Developer

When you partner with DistantJob for your next hire, you get the highest quality developers who will deliver expert work on time. We headhunt developers globally; that means you can expect candidates within two weeks or less and at a great value.

Increase your development output within the next 30 days without sacrificing quality.

Book a Discovery Call

What are your looking for?
+

Want to meet your top matching candidate?

Find professionals who connect with your mission and company.

    pop-up-img
    +

    Talk with a senior recruiter.

    Fill the empty positions in your org chart in under a month.